vue-router和axios的优化和封装

本地目录:

  • 1.router优化之路由懒加载
  • 2.router优化之token验证和动态设置路由
  • 3.axios优化之请求拦截器
  • 4.axios优化之封装通用api
  • 5.axios优化之基地址的环境适配

1.router优化之路由懒加载

修改router文件夹中的index.js文件
第一种方式,在引入组件的时候做出改变
原本的写法:
import Login from '@/components/Login'
懒加载的写法:
const Login = () => import(/* webpackChunkName: "Login" */ '../views/Login.vue')
第二种方式:在挂载路由的时候做出改变
原本的写法:

  {
    path: '/login',
    name: 'Login',
    meta: {
      title: '登录'
    },
    component: Login
  },

懒加载的写法:

  {
    path: '/login',
    name: 'login',
    meta: {
      title: '登录'
    },
    component: () => import(/* webpackChunkName: "login" */ '@/components/login')
  },

2.router优化之token验证和动态设置路由

这里我们用到了路由守卫

router.beforeEach((to, from, next) => {
  if (to.meta.title) {
    document.title = to.meta.title
  }
  if (to.path.startsWith('/login')) {
    window.localStorage.removeItem('access-token')
    next()
  } else if (to.path.startsWith('/index')) {
    next()
  } else {
    let user = window.localStorage.getItem('access-token');
    if (!user) {
      next({ path: '/login' })
    } else {
      next()
    }
  }
})

3.axios优化之请求拦截器

api文件夹是我们在项目的根目录文件夹下新建的,方便我们对axios进行深层的封装,这样我们就不在入口文件main.js中引用axios了,而是在需要发送请求的单独引入。
在api文件夹中新建一个index.js,然后先引用axios
import axios from 'axios'
添加请求拦截器(在请求头中添加token)

axios.interceptors.request.use(
  config => {
    let token = window.localStorage.getItem('access-token')
    if (token) {
      config.headers.Authorization = token;
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
);

添加响应拦截器(对指定的响应码进行统一的处理)

axios.interceptors.response.use(
  function(res) {
    // console.log('header: ', res)
    // token 快过期,交换
    if (res.headers['new-token']) {
      const newToken = res.headers['new-token']
      localStorage.setItem('token', newToken)
    }
    if (
      res.data.code === '200' ||
      res.data.code === '201' ||
      res.data.state === 'SUCCESS'
    ) {
      return res
    } else if (res.data.code === '400') {
      localStorage.removeItem('token')
      router.push('/login')
    } else {
      // Toast.fail(res.data.message)
      return Promise.reject(res)
    }
  },
  function(error) {
    // console.log(error.response.data.code)
    if (error.response) {
      const code = error.response.status
      const innerCode = error.response.data.code

      switch (code) {
        // 400 token 校验不通过,402 用户没权限, 401 token 过期
        case 400:
          localStorage.removeItem('token')

          if (router.currentRoute.name !== 'Login') {
            router.push('/login')
          }
          if (innerCode === '402') {
            // 402 的提示语会不一样
          }
          if (innerCode === '401' || innerCode === '402') return
      }
    }
    // 对响应错误做点什么
    error.message && Toast.fail(error.message)
    return Promise.reject(error)
  }
)

4.axios优化之封装通用api

还是在index.js文件中
首先需要一个基地址的变量base,因为项目从开发到上线,往往有多个环境,所以这个base需要根据不同的环境去进行自动改变。(适配方法接下来会讲),如果不懂这个base的设置,可以在一开始的时候把base写死
const base = 'xxxxx'
后面再根据实际情况进行改变

export const POST = (url, params) => {
  return axios.post(`${base}${url}`, params).then(res => res.data)
}
export const GET = (url, params) => {
  return axios.get(`${base}${url}`, {
    params: params
  }).then(res => res.data)
}
export const PUT = (url, params) => {
  return axios.put(`${base}${url}`, params).then(res => res.data)
}
export const DELETE = (url, params) => {
  return axios.delete(`${base}${url}`, {
    params: params
  }).then(res => res.data)
}
export const PATCH = (url, params) => {
  return axios.patch(`${base}${url}`, params).then(res => res.data)
}

index.js的代码已经写好,接下来在api文件夹下新建一些其他的文件,用来写页面中用到的具体请求

import * as API from './'
export default {
  list: params => {
    return API.GET('/api-base/log', params)
  },
  updateList: params => {
    return API.POST('/api-base/updatelist', params)
  }
}

在要用到这个list请求的页面首先引入api
import API from "../../api/api_log";
发送get请求示例

let params = {
  limit: that.limit,
  page: val
};
API.list(params).then(res => {
  if (res.code === 0) {
    that.rows = res.page.rows;
    that.total = res.page.total;
  }
});

post等其他方式的请求的发送方式和get一样,虽然在api文件夹的index.js文件夹中我们已经定义了所有请求的一些返回状态码的统一处理方式,但是我们也可以为单独请求定制错误处理代码,代码示例:

API.list(params)
  .then(
      function(result) {
        if (res.code === 0) {
        that.rows = res.page.rows;
        that.total = res.page.total;
      }else{
        //some code
       }
     },
    function(err) {
      _this.$message.error({
        showClose: true,
        message: err.toString(),
        duration: 2000
      });
    }
  )
  .catch(function(error) {
    console.log(error);
    _this.$message.error({
      showClose: true,
      message: "请求出现异常",
      duration: 2000
    });
  });

5.axios优化之基地址的环境适配

vue-cli3以前的版本生成的项目,根目录下会有build文件夹和config文件夹,存放的是关于webpack的配置,但是vue-cli3以后的版本,不再显示此文件,所有修改webpack只能通过添加代码去覆盖默认配置。
在根目录下新建一个vue.config.js文件,用来写相应的代码,如常用的配置css以及设置代理,代码示例:

module.exports = {
  // px转rem
  css: {
    extract: false,
    loaderOptions: {
      postcss: {
        plugins: [
          require('postcss-plugin-px2rem')({
            rootValue: 37.5, // 换算基数, 默认100  ,这样的话把根标签的字体规定为1rem为50px,这样就可以从设计稿上量出多少个px直接在代码中写多上px了。
            exclude: /(node_module)/, // 默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)\/如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
            mediaQuery: false, // (布尔值)允许在媒体查询中转换px。
            minPixelValue: 3 // 设置要替换的最小像素值(3px会被转rem)。 默认 0
          })
        ]
      }
    }
  },
  devServer: {
    open: true,
    host: '192.168.1.102',
    port: 8080,
    https: false,
    // 以上的ip和端口是我们本机的;下面为需要跨域的
    proxy: 'http://xxx.xx.xxx.xxx:8088'
  }
}

这里我们重点讲下基地址的环境适配的方法。
第一步
在项目的根目录建立额外的环境配置文件,一个文件一个环境,如我要配置test(测试环境)
.evn.test内容
NODE_ENV = 'test'
第二步
在项目根目录添加 config.js文件(此文件是配置各环境的url)

let BASE_URL = ""; //这里是一个默认的url,可以没有
switch (process.env.NODE_ENV) {
    case 'development':
        BASE_URL = "http://0.0.0.222:8080" //这里是本地的请求
        break
    case 'test':
        BASE_URL = "http://www.xxx.com.cn/test" // 测试环境
        break
    case 'production':
        BASE_URL = "http://www.xxx.com.cn/" //生产环境
        break
}

export default BASE_URL;

第三步
在package.json文件中,添加启动命令

// ...
"scripts": {
     "serve": "vue-cli-service serve",
     "test": "vue-cli-service build --mode test",  // 这一行
     "build": "vue-cli-service build"
},
// ...

用法:
在需要用到请求前缀的地方,导入config文件,就可以了(比如封装的axios)
此方法配置后:
1、如果是本地环境,就运行npm run serve。此时对应的baseUrl就是config里配置的development项
2、如要打包到测试环境,就运行npm run test。此时对应的baseUrl就是config里配置的test项
3、如要打包到正式环境,就行动npm run build。此时对应的baseUrl就是config里配置的production项

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351