vue动态引入及axios封装(基础和进阶)---小白入门

vue动态引入及axios封装的扩展和总结

  • 一.vue基础
    • 1.axios的基础用法.
    • 2.router的基础用法
  • 二.vue的进阶
    • 1.axios进阶
      • (1).先看看axios如何进行封装
      • (2).在src目录下面的request目录下创建common.js文件
      • (3).在src目录下创建common文件夹,在此文件夹下面创建api.js,代码如下:
    • 2.router进阶
      • (1).修改路由配置,按模块写路由文件
      • (2).封装获取路由文件函数
      • (3).扩展
  • 三.结尾

最近总结了一下vue的基础和进阶的方法,想给大家分享一下,小菜鸟献丑啦!!!

一.vue基础

本例是通过2.x版本的vue来介绍:
通过 vue init webpack demo,然后 npm install axios 安装axios, 创建一个基于webpack的一个名为demo的项目,目录结构如下:

vue动态引入及axios封装(基础和进阶)---小白入门_第1张图片

首先,我们找到入口文件main.js,一般的话,比如我们要请求接口使用各种ui框架,我们都会在main的js引入,这里我们引入axios来举例.

1.axios的基础用法.

import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'

Vue.config.productionTip = false

Vue.prototype.$axios = axios; // 有没有觉得这个方法这样写似曾相识

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: ''
})

比如:我想引入一个axios当做请求的一个工具,我在main.js全局引入,通过 a x i o s 这 样 引 入 , 这 样 可 以 再 其 他 页 面 通 过 t h i s . axios这样引入 ,这样可以再其他页面通过 this. axios,this.axios 调用此方法,紧接着,我们又会想到,既然请求有了,那么我们怎么样做到给请求做一下拦截呢?

import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'

Vue.config.productionTip = false

Vue.prototype.$axios = axios; // 有没有觉得这个方法这样写似曾相识

//以登录为例
function getToken(){
	let token = sessionStorage.getItem('token') || '';
    return token;
}
//设置请求拦截
axios.interceptors.request.use(
	config => {
		if(getToken){
			config.headers["token"] = getToken();
		}
		return config;
	},
    error => {
        return Promise.reject(error);
    }
)
//设置响应拦截
axios.interceptors.response.use(
	response => {
        let res = response.data;
        if(res.code == 401){
            location.href = '/' //这里可以做一些简单的处理,根据业务需求来决定
        }
        return Promise.resolve(res)
    },
    error => {
        return Promise.reject(error);
    }
)

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: ''
})

像这样我们就做了一个基础的axios请求拦截和响应的功能,看起来是这么回事,但是有没有想过,把这些东西都放在main.js里面代码是不是觉得很臃肿? 后面我们再一起讲解该怎么去改,优化一下.

2.router的基础用法

接下来看看基础的路由配置写法:

import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/components/Login'
import List from '@/components/List'

Vue.use(Router)
export default new Router({
  mode: 'history',
  routes: [
  	 {
       path: '/',
       name: 'Login',
       component: Login
     },
     {
       path: '/list',
       name: 'list',
       component: List
     }
  ]
})

平时,我们在做项目,比如做商城啊,管理后台啊这类型的项目都有一个登录,列表页等东西, 所以我们会给每一个页面指定一个路由,就会在router里面头部引入各个页面,并对各个页面的路由配置路由地址,然后将该Router暴露出去,并且在main.js中引入使用,
假设我们有20个或30个路由呢,那岂不是要引入20,30次?这样会不会太过于频繁,代码不美观,有没有办法可以简化这样的引入方式呢?

二.vue的进阶

看了上面Vue的基础路由及axios的基础写法,代码臃肿,写的东西比较繁多,有没有更好的写法,让代码看起来更加简洁明了呢?

1.axios进阶

接下来,我们一起看看vue的进阶用法吧! 下面我们以post请求为例

(1).先看看axios如何进行封装

//首先,我们在src目录下创建request文件夹,里面创建一个axios.js文件
import axios from 'axios';

//获取token
function getToken(){
    let token = sessionStorage.getItem('token') || '';
    return token;
}

//创建一个axios的实例
const service = axios.create({
    baseURL: '/apply', //代理 api的url
    timeout: 5000       //请求超时的时间
})

//request请求拦截器
service.interceptors.request.use(
    config => {
        if(getToken()){
            config.headers["token"] = getToken();
        }
        return config;
    },
    error => {
        return Promise.reject(error)
    }
)

//response响应拦截器
service.interceptors.response.use(
    response => {
        let res = response.data;
        if(res.code == 401){
            // location.href = '/'  这里可以做一下操作,也可以扩展一些需求,根据项目实际情况来定
        }
        return Promise.resolve(res)
    },
    error => {
        return Promise.reject(error);
    }
)
export default service;

(2).在src目录下面的request目录下创建common.js文件

import service from './axios';
export default function requestOfPost(url, data) {
    return service.post(url, data)
}

引入刚刚写好的axios文件暴露出来的方法,封装在一个函数里面,待使用的时候进行调用.

(3).在src目录下创建common文件夹,在此文件夹下面创建api.js,代码如下:

import requestOfPost from '../request/common';
export function postRequest(url,data){
    return new Promise((resolve,reject)=>{
        requestOfPost(url,data).then(res=>resolve(res)
        ,error => reject(error))
    })
}
//目的是为了获得除了data数据意外的比如 headers config等

创建一个request目录下面的apiUrl.js文件

const url = {
    loginUrl: '/login',
    getMenuList: '/getMenuList'
}
export default url;

为什么要这样定义接口呢? 为了安全性,避免直接将接口写在文件里面,webpack打包将接口暴露在打包文件里面.
为什么要引入刚刚写好的service文件呢,因为,我们在平时开发中,不仅仅需要用到data里面的数据,还可能需要获得头部信息等其它信息,这时候就要封装一层Promise,将请求成功或失败的结果抛出,以便调用时可以拿到数据.
我们在调用的时候可以这样写
import url from "../request/apiUrl";
import { postRequest } from "../common/api";
postRequest(url.loginUrl,params).then(res=>console.log(res))
这样通过.then() 方法就可以拿到你想要的数据或者请求头等信息.

在这里提供多一种ES7的请求方式

async loginBtn() {
   //当请求发送错误不会执行下面的代码
   let loginData = await postRequest(url.loginUrl, params);
   console.log(loginData) //这里可以直接拿到结果,不需要.then(res=>console.log(res))
},

这里要注意 async和await要一起使用,还有一点需要注意的是,如果这个请求失败了 下面的代码是不会执行了,可以适当利用try{}catch(error){}解决这一问题.

2.router进阶

接下来我们回想一下上面写的router文件

代码臃肿,如果一个项目有很多个文件,那么必须引入很多次,这时候我们可以想想,有没有什么办法可以让这些页面不用一个一个手写引入呢?

这时候我们可以把router文件改成如下:

(1).修改路由配置,按模块写路由文件

提取login路由文件


// src下面的router下面的login.routes.js
export default {
    path: '/',
    name: 'Login',
    component: () => import('@/components/Login.vue'), //路由懒加载
    children: [

    ]
}

提取list路由文件

// src下面的router下面的list.routes.js
export default {
    path: '/list',
    name: 'List',
    component: () => import('@/components/List.vue'), //路由懒加载
    children: [

    ]
}

(2).封装获取路由文件函数

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
/*
require.context函数接受三个参数

directory {String} -读取文件的路径

useSubdirectories {Boolean} -是否遍历文件的子目录

regExp {RegExp} -匹配文件的正则

require.context('./',true,/\.routes\.js/) 返回一个函数
*/

const routerList = [];
function importAll(r) {
  console.log(r,'我是r') //返回一个函数
  console.log(r.keys(),'我是r.keys()')//返回匹配成功模块的名字组成的数组
  r.keys().forEach((key) => {
    console.log(r(key),'我是r(key)') //返回 {default: {路由,组件等信息}}
    routerList.push(r(key).default)
  })
}
importAll(require.context('./',true,/\.routes\.js/));
const routes = [
  ...routerList
];


export default new Router({
  mode: 'history',
  routes
})

由上面代码,我们可以可知,写了一个require.context方法,用来匹配与之相关的文件,通过r.keys(),拿到匹配成功模块的路径组成的一个数组形式,紧接着变量这个数组,通过r(key)将这个数组传进去,得到{default: {path: '/',component:xxx}}这样的参数,所以我们取出对象里面的default,将这个对象添加到定义的空数组里面,将这个数据扩展到routes里面,这样就可以动态的获得与之匹配的文件.
在这里插入图片描述
但是,要注意的是,我们每一个模块对应的路由要分别写在router下面,并且名称后缀都为.routes.js结尾

(3).扩展

如果我们在登录后还想对某些页面进行,是否登录后才可以跳转操作等其它功能,我们可以进行如下修改:

//router/list.routes.js
export default {
    path: '/list',
    name: 'List',
    component: () => import('@/components/List.vue'), //路由懒加载
    children: [

    ],
    meta:{
        //自定义字段
        mustLogin: true
    }
}

//main.js文件可以对拦截器做一些处理
router.beforeEach((to, from, next) => {
  let token = sessionStorage.getItem('token');
  if (to.meta.mustLogin) {
    if (token) {
      next();
      console.log('需要登录,有token')
    } else {
      next({
        path: '/'
      });
      console.log('需要登录,无token')
    }
  }else{
    next();
    console.log('无需要登录,无token')
  }
})

通过在路由里面定义一个meta属性,在路由前置守卫判断,如果该 mustLogin为true说明这个页面必须登录后才可以登录,如果未登录则跳到登录页.如果在请求拦截有其他公共的操作,可以再axios.js文件下面修改 以公司返回的状态码为准,去修改即可…

三.结尾

今天给大家分享的就是 vue的路由(Router)使用基础及进阶和vue的请求(axios)使用基础和进阶,总的来说,其实难点不多,就是一个require.context函数的理解和使用没怎么接触过,其他都是大家平时项目中用到的东西,
写的如果有什么不足之处,恳请大家指出来,大家一起交流交流!!!

你可能感兴趣的:(Vue)