vue-element-admin与后端交互流程(补)(跨域)

  • Post author:
  • Post category:vue

有些朋友说,一个交互过程东一下,西一下的,不知所以然,所以在此补一下vue-element-admin的整体框架结构,并细说一下交互的过程,包括跨域问题!

一:首先是整体框架结构:

├── build                      // 构建相关(build.js/webpack等)
├── config                     // 配置相关 (代理环境配置/local端口配置等等)
├── dist                       //打包后的dist文件 (供发布到线上使用)
├── src                        // 源代码
│   ├── api                    // 所有请求
│   ├── service                //请求(和api相同,我习惯写到这里,更语义化)
│   ├── assets                 // 主题 字体等静态资源
│   ├── components             // 全局公用组件
│   ├── directive              // 全局指令
│   ├── filters                // 全局 filter
│   ├── icons                  // 项目所有 svg icons
│   ├── lang                   // 国际化 language
│   ├── mock                   // 项目mock 模拟数据
│   ├── router                 // 路由
│   ├── store                  // 全局 store管理
│   ├── styles                 // 全局样式
│   ├── utils                  // 全局公用方法 (可以封装一下cookie或者request的一些函数)
│   ├── vendor                 // 公用vendor
│   ├── views                  // views 所有页面 (一般要和api/service起名相同,方便迭代)
│   ├── App.vue                // 入口页面
│   ├── main.js                // 入口文件 加载组件 初始化等
│   └── permission.js          // 权限管理 (根据权限配置路由)
├── static                     // 第三方不打包资源
│   └── Tinymce                // 富文本
├── .babelrc                   // babel-loader 配置
├── .eslintrc.js               // eslint 配置项
├── .gitignore                 // git 忽略项
├── .travis.yml                // 自动化CI配置
├── favicon.ico                // favicon图标
├── index.html                 // html模板
└── package.json               // package.json

ok,我想框架结构上在上面已经写的很详细了,下面说一下一个交互的具体实现流程吧

1.首先是在view页面进行交互提交,这个就不多说了,页面级的

2.点击提交后会调用api/service里的请求函数

3.请求函数会调用之前封装好的axsio请求函数

4.接收后端返回的response然后进行view的data渲染

下面附代码细说一下

// views/ceshi
<button @click="ceshia">举例测试</button>

import { ceshi } from '@service/ceshi'
export default {
  data() {
    list: '',
    tokon: 'suibian'
  },
  methods: {
    ceshia() {
      ceshi(this.tokon).then(res => {
        this.list = res.data.list
      })
    }
  }
}

其中的from的ceshi.js函数里如下写

import request from '@utils/request'  //引入request中封装的请求函数,包括请求拦截器,response,error等操作

export function ceshi(data) {
  return ruquest ({
    url: 'i/suibian/suibian/suibian',
    method: 'post',
    data
  })
}

之后是调用utils/request,里面这样写

import store form '@store' //引入vuex,因为需要在这里根据角色获取路由id,并在store中进行更改

// create an axios instance
const service = axios.create({
  baseURL: process.env.BASE_API, // api的base_url
  timeout: 5000 // request timeout
})

// request interceptor
service.interceptors.request.use(
  config => {
    // Do something before request is sent
    return config
  },
  error => {
    // Do something with request error
    console.log(error) // for debug
    Promise.reject(error)
  }
)

// respone interceptor
service.interceptors.response.use(
  // response => response,
  /**
   * 下面的注释为通过在response里,自定义code来标示请求状态
   * 当code返回如下情况则说明权限有问题,登出并返回到登录页
   * 如想通过xmlhttprequest来状态码标识 逻辑可写在下面error中
   * 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除
   */
  response => {
    const res = response.data
    if (res.error_code !== 0) {
      Message({
        message: res.error_msg,
        type: 'error',
        duration: 2 * 1000
      })
      // 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;
      if (res.error_code === 10009) {
        // 请自行在引入 MessageBox
        // import { Message, MessageBox } from 'element-ui'
        MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
          confirmButtonText: '重新登录',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          store.dispatch('FedLogOut').then(() => {
            location.reload() // 为了重新实例化vue-router对象 避免bug
          })
        })
      }
      return Promise.reject(response.data)
    } else {
      return response.data
    }
  },
  error => {
    const reg = new RegExp(/504|503|500|400/)
    if (reg.test(error.message) || error.message === 'Network Error') {
      Message({
        message: '网络断了,请检查网络!',
        type: 'error',
        duration: 5 * 1000
      })
    } else {
      Message({
        message: error.message,
        type: 'error',
        duration: 5 * 1000
      })
    }
    return Promise.reject(error)
  }
)

下面来说一下跨域问题:利用vue-element-admin已安装的proxy来处理

1.在config/index.js里配置dev的proxyTable参数

proxyTable: {
      '/lizi': { //这个是公共部分http://aaa.bbb.com/lizi
        target: 'http://aaa.bbb.com', //真实的服务器地址1
        target: 'http://ccc.ddd.com', //真实的服务器地址2
        changeOrigin: true //开启代理
      }
    },

2.在编写请求实例的时候注释掉BASE_API,utils/request.js

const service = axios.create({
  //baseURL: process.env.BASE_API, // api的base_url
  timeout: 5000 // request timeout
})

3.在api的封装请求函数中如此写

//封装一个例子
export function lizi(data) {
  return request({
    url: '/lizi/aaa/bbb/ccc',
    method: 'post',
    data
  })
}

备注:如果不用moke.js的话记得在main.js中把引用moke的给注释掉


版权声明:本文为wangle_style原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。