vue-element-admin與後端互動流程(補)(跨域)

wangle_style發表於2019-03-06

有些朋友說,一個互動過程東一下,西一下的,不知所以然,所以在此補一下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的給註釋掉

相關文章