花裤衩建议

你可以把 vue-element-admin当做工具箱或者集成方案仓库,在 vue-admin-template 的基础上进行二次开发,想要什么功能或者组件就去 vue-element-admin 那里复制过来。

vue-admin-template/src下的目录结构:
.
├── App.vue //入口
├── api // 各种接口
├── assets // 图片等资源
├── components // 各种公共组件,非公共组件在各自view下维护
├── icons //svg icon
├── main.js //入口
├── permission.js //认证入口
├── router // 路由表
├── store // 存储
├── styles // 各种样式
├── utils // 公共工具,非公共工具,在各自view下维护
└── views // 各种layout


git clone https://github.com/PanJiaChen/vue-admin-template

1. 登录前端

1.1. 登录过程源码解析

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

1.2. 登录配置

1.2.1. 修改Vue配置,替换mock

打开/vue.config.js文件,在devServer配置下,增加代理proxy内容,如下所示:

  devServer: {
    port: port,
    open: true,
    overlay: {
      warnings: false,
      errors: true
    },
    proxy: {
      [process.env.VUE_APP_BASE_API]:{
        target:'http://localhost:8090', //后期可以改
        changeOrigin:true,
        pathRewrite:{
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      },
    },
    after: require('./mock/mock-server.js')
    //before: require('./mock/mock-server.js')
  },

1.2.2. 配置环境(env.development)后端代理

打开/.env.development文件

# just a flag
ENV = 'development'

# base api
# VUE_APP_BASE_API = '/dev-api'   //替换后端地址
VUE_APP_BASE_API = 'http://localhost:8090/'

1.2.3. 与后端接口API

打开/src/api/user.js文件,可以使用原接口名称,也可以自定义。(本文使用原名称)

import request from '@/utils/request'

export function login(data) {
  return request({
    url: '/user/login',
    method: 'post',
    data
  })
}

export function getInfo(token) {
  return request({
    url: '/user/info',
    method: 'get',
    params: { token }
  })
}

1.3. 登录过程解析

本小节主要讲解登陆的流程以及我认为这个框架的厉害的东西:动态路由,之前看代码的时候,总想着一个登录搞那么麻烦,后面仔细品味发现原来一个小小的登录功能涉及到了这么多的东西。[6]

隆重推出/src/permission.js!
在登录过程中,permission.js是路由的全局钩子(beforeEach和afterEach),全局钩子的意思就是每次跳转的时候可以根据情况进行拦截,不让它进行跳转。主要使用场景就是有些页面需要用户登录之后才能访问,就可以在beforeEach中校验用户是否登陆来进行相对应的拦截处理。如代码所示。

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
  const hasToken = getToken()

  if (hasToken) {
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({ path: '/' })
      NProgress.done()
    } else {
      // determine whether the user has obtained his permission roles through getInfo
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
      if (hasRoles) {
        next()
      } else {
        try {
          // get user info
          // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
          const { roles } = await store.dispatch('user/getInfo')

也就是说,登录过程由二维控制,普通过程是登录页(/src/views/login/index.vue)、输入用户名和密码(login)到后台python验证反馈code=20000和token、成功后路由(router)到主页;而另个permission过程是监控router动作,截取用户信息和token,如果已经登录但是没有用户信息,则调用getinfo(/src/api/user.js)接口。

[6]用一句话来概括:是否登陆?没有就给我老老实实登陆。是否有用户信息?没有就给我获取用户信息,并且生成可访问路由然后利用addRoutes进行添加。这两步都是actions:user/getInfo,permission/generateRoutes。

详见如下过程:

  1. 进入首页
    首先判断是否有token,如果没有,则到登录页面(router指向过程:“next({ path: ‘/’ })”)。
  2. 登录页
    /src/views/login/index.vue
    点击登陆之后发生的第一个就是handleLogin方法。首先利用validate方法进行表单验证,再调用user/login方法,这个user/login是什么呢?一起来揭开它神秘的面纱。
    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 || '/' })
  1. user/login
    /src/store/modules/user.js
    简单的说就是登陆验证,登陆成功之后,分别保存token到vuex、cookie中。
  // user login
  login({ commit }, userInfo) {
    const { username, password } = userInfo
    return new Promise((resolve, reject) => {
      login({ username: username.trim(), password: password }).then(response => {
        const { data } = response
        commit('SET_TOKEN', data.token)
        setToken(data.token)
        resolve()

在这里插入图片描述

2. 登录的后端

对于使用了Python的Tornado框架,设计发布为REST规范的webservice,.这里使用pyrestful的插件,pyRestful是一个API,用于使用Tornado Web服务器开发restful服务。

//这段代码是src/api/user.js中的代码,与后端接口的API
import request from '@/utils/request'

export function login(data) {
  return request({
    // 这里替换成自己的登陆接口,下面的也是一样
  return request({
    url: '/user/login',
    method: 'post',
    data
  })
}

export function getInfo(token) {
  return request({
    url: '/user/info',
    method: 'get',
    params: { token }
  })
}

2.1. 后端开发需要提前准备的

2.1.1. 跨域问题

Access to XMLHttpRequest at ‘http://localhost:8090/user/info?token=admin-token’ from origin ‘http://localhost:9528’ has been blocked by CORS policy: Request header field x-token is not allowed by Access-Control-Allow-Headers in preflight response.

由于API调用header中有token,需要为“Access-Control-Allow-Headers”增加“x-token”内容。通过Fiddler监控发现Vue的axios未构造、传递Http Header,需要自行设置,如下代码所示。

class UserResource(pyrestful.rest.RestHandler):
    """解决JS跨域请求问题"""
    def set_default_headers(self):
        self.set_header('Access-Control-Allow-Origin', '*')
        self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
        self.set_header('Access-Control-Max-Age', 1000)
        self.set_header('Content-type', 'application/json; charset=UTF-8')
        self.set_header('Access-Control-Allow-Credentials', 'true')
        self.set_header('Access-Control-Allow-Headers', 'Content-Type, x-token')    # 后增加’ x-token‘

注:当然,可以使用Axios构造header,也能解决。不过本着依赖vue-element-admin原则,尽量不修改前端代码,特别是核心架构代码,则采用在后端由python来解决。

由于tornado及pyrestful未对“OPTIONS”做处理,需要自行接受OPTION信息,代码很简单,直接透明越过。

class UserResource(pyrestful.rest.RestHandler):
    ......
    def options(self):
        pass

2.1.2. rest API测试与监控

2.1.2.1 POSTMAN

使用Postman的Chrome插件,测试Rest API,效果如下:
在这里插入图片描述

2.1.2.2 Fiddler

Fiddler是最强大最好用的Web调试工具之一,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据。

通过Fiddler工具,监控输入request和返回response。
在这里插入图片描述

2.2. 源代码

由于这部分采用基于pyrestful插件实现,很多过程简化,为了快速演示整体架构技术实现,后台数据处理略过,直接返回需要的结果,达到技术实现的目标。

import tornado.ioloop
import pyrestful.rest

from pyrestful import mediatypes
from pyrestful.rest import get, post, put, delete
import os
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'

class User(object):
    username = str
    password = str

class UserResource(pyrestful.rest.RestHandler):
    """解决JS跨域请求问题"""
    def set_default_headers(self):
        self.set_header('Access-Control-Allow-Origin', '*')
        self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
        self.set_header('Access-Control-Max-Age', 1000)
        self.set_header('Content-type', 'application/json; charset=UTF-8')
        self.set_header('Access-Control-Allow-Credentials', 'true')
        self.set_header('Access-Control-Allow-Headers', 'Content-Type, x-token')    # 后增加’ x-token‘
    
    @get(_path="/user/info", _types=[str], _consumes=mediatypes.APPLICATION_JSON,_produces=mediatypes.APPLICATION_JSON)
    def info(self, token):
        print('start info!')
        user = User()
        user.username = token
        print(token)  

        return {'code':20000,'data': {
                'roles': ['admin'],
                'introduction': 'I am a super administrator',
                'avatar': 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
                'name': 'Super Admin'
              }}

    @post("/user/login",{'format':'json'},_catch_fire=True)
    def login(self,user):
        userinfo = self.request.body        
        print(user)
        
        return {"code":20000,"data":{"token":"admin-token"}}
   
    
    def options(self):
        pass

if __name__ == '__main__':
    try:
        print("Start the service")
        app = pyrestful.rest.RestService([UserResource])
        http_server = tornado.httpserver.HTTPServer(app)
        #http_server.listen(8090,address='192.168.16.71')
        http_server.listen(8090)
        tornado.ioloop.IOLoop.instance().start()
    except KeyboardInterrupt:
        print("\nStop the service")

服务运行效果如下:

Start the service
b'{"username":"admin","password":"123456"}'
{'username': 'admin', 'password': '123456'}
start info!

通过短暂时间的分析与实践,vue-element-admin/template比较易用,外行短时间就能投入到业务实现中。

由于时间紧迫,先写到这样,欢迎反馈交流。

参考:

[1]《vue-element-admin登录流程》 CSDN博客 , 兔子零84 , 2019年09月
[2]《Vue 新手学习笔记:vue-element-admin 之登陆及目录权限控制》 CSDN博客 ,乐之终曲 ,2019年05月
[3]《Access-Control-Allow- 设置 跨域资源共享 CORS 详解》 CSDN博客 ,Normal Developer , 2017年12月
[4]《Cross-Origin Resource Sharing (CORS》) MDN web docs
[5]《使用vueAdmin开发后台管理系统(登录篇)》 CSDN博客 ,zw沐知 , 2020年7月
[6]《vue-element-admin 登陆详解》 艺宵博客 ,Vedu , 2020年08月
[7]《Nginx+Vue.js+Tornado前后端分离架构环境实践(3)》 CSDN博客 ,肖永威 ,2020年10月
[8]《Python基于Flask开发Restful API实践》 CSDN博客 ,肖永威 ,2018年7月
[9]《VUE中使用HTTP库Axios方法详解》 脚本之家 , 小火柴的蓝色理想 ,2020年2月

Logo

前往低代码交流专区

更多推荐