当前位置:   article > 正文

详细分析 vue-admin-template

vue-admin-template

vue教程1

vue教程2

vue教程3

1、整体效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、目录分析

一、目录结构

在这里插入图片描述

二、配置信息

vue.config.js

这里面配置了项目的基本信息: 所使用的环境、端口号、对外路径、输入文件路径等信息 , 可以看到我们使用的dev开发环境,下面将查看开发环境的配置

const port = process.env.port || process.env.npm_config_port || 9528 // dev port

// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = {
  /**
   * You will need to set publicPath if you plan to deploy your site under a sub path,
   * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
   * then publicPath should be set to "/bar/".
   * In most cases please use '/' !!!
   * Detail: https://cli.vuejs.org/config/#publicpath
   */
  publicPath: '/',
  outputDir: 'dist',
  assetsDir: 'static',
  lintOnSave: process.env.NODE_ENV === 'development',
  productionSourceMap: false,
  devServer: {
    port: port,
    open: true,
    overlay: {
      warnings: false,
      errors: true
    },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

.env.development

在这里会标注我们后台的路径, 此时因为使用的是mock数据, 所有只是提供了一下路径而已。以及标注当前文件的类型

ENV = ‘development’ 此时便引入了与后端数据交互, 与后端的交互接口都在 api的文件家里面。

# just a flag
ENV = 'development'
# base api
VUE_APP_BASE_API = '/dev-api'
  • 1
  • 2
  • 3
  • 4

三、主要文件分析

api 文件夹

截取user.js 文件里面的一部分, 可以看到这个文件会向后端发送http请求, 但是它使用的是 /utils/request 里面的内容

先说明此文件的作用, 在这个开源框架中与后端交互使用的是 axios 组件。指定请求的路径、类型、请求参数、请求体参数, 就可以执行异步亲求了。下一步介绍 /utils/request

import request from '@/utils/request'

export function login(data) {
  return request({
    url: '/vue-admin-template/user/login',
    method: 'post',
    data
    params
  })
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

/utils/request

首先创建一个axios的实例, 对于这个实例需要设定的有: 基本的URL、以及请求超时的。

// create an axios instance
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

第二步是添加拦截器, axios每次请求都会经过这个拦截器。 store.getters.token 首先从全局状态管理那里判断 token , 有的话就可以请求, 否则就抛出异常。并且可以清楚的看到如果有 token的话, 我们在请求的时候会得到当前的token 并且直接添加到请求头中, 以便后端得到当前登录的信息。

// request interceptor
service.interceptors.request.use(
  config => {
    // do something before request is sent

    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['X-Token'] = getToken()
    }
    return config
  },
  error => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

下面是对返回结果的拦截, 在这里会判断返回结果中的状态码, 根据状态码来判断这次请求的状态如何。

// response interceptor
service.interceptors.response.use(

  response => {
    const res = response.data
    // if the custom code is not 20000, it is judged as an error.
    if (res.code !== 20000) {
      Message({
        message: res.message || 'Error',
        type: 'error',
        duration: 5 * 1000
      })

      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
        // to re-login
        MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
          confirmButtonText: 'Re-Login',
          cancelButtonText: 'Cancel',
          type: 'warning'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

最后将 axios的实例导出 export default service, 在这里我们看到了 store.getters.token 以及文件最上面的导入

import store from '@ /store'
store.getters.token // 下一步查看  /store  这个文件夹
  • 1
  • 2

/store

简单介绍此文件中几个重要的知识点

  • ​ State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储
  • ​ Mutation用于修改变更$store中的数据
  • 在mutations中不能编写异步的代码,会导致vue调试器的显示出错。在vuex中我们可以使用Action来执行异步操作。
  • Getter用于对Store中的数据进行加工处理形成新的数据
    它只会包装Store中保存的数据,并不会修改Store中保存的数据,当Store中的数据发生变化时,Getter生成的内容也会随之变化
  token: state => state.user.token,
  • 1

在 gettes 文件中我们看到了 token 这个标识, 其中 gettes 文件就是为了我们方便从全局状态管理中获取数据的工具, 在这里可以得到当前的 token 。

此文件主要是使用了 vuex , 而 vuex 是 vue中的全局的状态管理, 方便我们进行组件之间的数据传递。基本使用如下

this.$store.state.count // 得到store中值

// 调用Acton中的异步方法 user.js 中的login 方法  , 这个是 /veew/login 文件中的代码 
this.$store.dispatch('user/login', this.loginForm).then(() => {
     this.$router.push({path: this.redirect || '/'})
      this.loading = false
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

token 相关的

  RESET_STATE: (state) => {
    Object.assign(state, getDefaultState())
  },
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

登录相关的

举例说明 login 方法, 首先 传入 {commit} 以及在方法中 commit(‘SET_TOKEN’, data.token) 这两个的作用是执行 action 中异步方法的简写, 组用就是设置 token 的值, 我们知道修改 store中的数据需要使用 Mutation 就是会调用上面的 SET_TOKEN 把 后端返回的token 保存到vuex中, 并且使用 setToken(data.token) 方法把 token写入到 cookie中 以便我们每次请求都可以带上这个 cookie , 并且能够解析出当前登录的用户 。

  // user login
  login({commit}, userInfo) {
    console.log('login')
    const {username, password} = userInfo
    console.log("user info ->>>>" + username + "=>>>" + password)
    return new Promise((resolve, reject) => {
      login({username: username.trim(), password: password}).then(response => {
        const {data} = response
        commit('SET_TOKEN', data.token)
        console.log(data.token)

        setToken(data.token)
        resolve()
      }).catch(error => {

        reject(error)
      })
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在这个文件中我们还可以观察到最上面存在组件的导入, 这就和之前的说明相匹配。

import {login, logout, getInfo} from '@/api/user'
import {getToken, setToken, removeToken} from '@/utils/auth'
import {resetRouter} from '@/router'
  • 1
  • 2
  • 3

main.js

这个是项目的入口文件, 在这个入口文件中, 我们看到当前是使用mock数据, 并且全局挂在 element - ui 以及在vue的实例中挂载了 路由、store (vuex) , 那下一步开始讲解路由

if (process.env.NODE_ENV === 'production') {
  const { mockXHR } = require('../mock')
  mockXHR()
}

// set ElementUI lang to EN
// Vue.use(ElementUI, { locale })
// 如果想要中文版 element-ui,按如下方式声明
Vue.use(ElementUI)

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

/ router

使用vue router的第一步是需要一个路由表、以及把路由表加载到路由实例中, 最后把路由实例导出。下面就是定义的路由表, 对于路由表 中包括

  • path : 访问的路径
  • component : 此路由对于的组件
  • hidden : 是否在界面显示此路由
  • meta : 设置路由的属性, 图标之类的
  • name : 路由名字
  • children : 该路由下的子路由, 效果就是二级菜单
export const constantRoutes = [
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true,
          children: [
      {
        path: 'https://panjiachen.github.io/vue-element-admin-site/#/',
        meta: {title: 'External Link', icon: 'link'}
      }
  },
  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

下面就是新建路由实例, 以及添加路由表, 导出路由。 上面介绍到了组件, 下一步解释路由对应的组件

const createRouter = () => new Router({
  // mode: 'history', // require service support
  scrollBehavior: () => ({y: 0}),
  routes: constantRoutes
})

const router = createRouter()

// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

/view/login/login.vue

组件的概念比较广泛,可以暂时理解为一个界面, 下面是登录的界面, name: ‘Login’, 定义的组件名称。 当在路由表中配置了此路由的信息后,就可以在使用中根据对应的path 来访问此路由。

<template>
  <div class="login-container">
  </div>
</template>
<script>
  import {validUsername} from '@/utils/validate'
  export default {
    name: 'Login',
    data() {
    },
    watch: {
    },
    methods: {
    }
  }
</script>

<style lang="scss">

</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

permission.js

此文件是用来配合路由使用的, 对于vue router 而言它还附带了一些其他的信息, 比如路由守卫, 在路由守卫中我们可以在路由跳转之前来做一些事情的。

对于此项目来讲;

1、首先判断是否有token

2、没有token , 如果在白名单里面, 就直接放行, 否则就直接强制跳转登录。

3、有token , 如果是 /login 就就直接到 根目录下

4、不是 /login 就去 store 里面找 当前用户的信息, 然后在放行

const whiteList = ['/login'] // no redirect whitelist

router.beforeEach(async(to, from, next) => {
  // start progress bar
  NProgress.start()
  // set page title
  document.title = getPageTitle(to.meta.title)
  // determine whether the user has logged in
  //console.log(getToken())
  const hasToken = getToken()

  if (hasToken) {
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({ path: '/' })
      NProgress.done()
    } else {
      const hasGetUserInfo = store.getters.name
      if (hasGetUserInfo) {
        next()
      } else {
        try {
          // get user info
          await store.dispatch('user/getInfo')
          next()
        } catch (error) {
          // remove token and go to login page to re-login
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    /* has no token*/
    if (whiteList.indexOf(to.path) !== -1) {
      // in the free login whitelist, go directly
      next()
    } else {
      // other pages that do not have permission to access are redirected to the login page.
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

3、登录流程

一、流程分析

如果是在项目初始化的情况下, 当前的配置如下 并且使用的是 mock 数据

  • 环境 lintOnSave: process.env.NODE_ENV === ‘development’, vue.config.js 中
  • VUE_APP_BASE_API = ‘/dev-api’ .env.development 中
  • before: require(‘./mock/mock-server.js’) vue.config.js 中

1、/view/login/login

这里是处理登录按钮的,点击登录之后会执行 store中的异步方法

      async handleLogin() {
        this.$refs.loginForm.validate(valid => {
          if (valid) {
            this.loading = true
            this.$store.dispatch('user/login', this.loginForm).then(() => {
              this.$router.push({path: this.redirect || '/'})
              this.loading = false
            }).catch(() => {
              this.loading = false
            })
          } else {
            console.log('error submit!!')
            return false
          }
        })
      }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2、/store/modules

这里会得到输入的用户名以及密码。 并且执行 login 方法, 把返回的token , 保存到 vuex、cookie 中(在路由守卫中 / login 是白名单会直接放行、axios 的请求拦截中 添加的是一个空值)

  login({commit}, userInfo) {
    console.log('login')
    const {username, password} = userInfo
    console.log("user info ->>>>" + username + "=>>>" + password)
    return new Promise((resolve, reject) => {
      login({username: username.trim(), password: password}).then(response => {
        const {data} = response

        commit('SET_TOKEN', data.token)
        console.log(data.token)

        setToken(data.token)
        resolve()
      }).catch(error => {

        reject(error)
      })
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

二、请求分析

​ 我们的登录请求会先经过 路由守卫判断是否存在 token, 如果不存在就会直接跳出登录界面, 路由守卫通过之后向后端发起请求, 而请求会被 axios拦截,为请求头添加上 token信息, 请求结束后 axios会拦截我们的响应信息对状态码进行判断。 一切符合就会放行,,,,,,,,

4 切换本地接口

链接:

https://blog.csdn.net/qq_41291945/article/details/107748623
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/400784
推荐阅读
相关标签
  

闽ICP备14008679号