### Vue.js
## 一、 axios的封装
### 1.1在src根目录 新建providers文件 ,以及添加几个主要的 文件
|---providers
|-----util.js 工具函数
|-----api.js 接口地址
|-----axios.js 封装axios的文件
mkdir providers
touch util.js api.js axios.js
### 1.2 配置工作环境 (dev,test,build)
安装:
yarn add cross-env -D
在package.json里配置:
"scripts": {
"test":"cross-env scene=test webpack --config webpack.config.js",
"dev":"cross-env scene=dev webpack-dev-server --config webpack.config.js",
"build":"cross-env scene=prod webpack --config webpack.config.js"
},
在配置文件webpack.config.js通过内置插件DefinePlugin配置
var webpack = require(‘webpack‘);
plugins.push(new webpack.DefinePlugin({
‘sceneParam‘: JSON.stringify(process.env.scene),
‘laney‘:JSON.stringify(‘laney‘),
‘test‘:‘"kkkkk"‘
}));
重新启动就可以在项目中直接获取到 sceneParam 参数
### 1.3 添加登陆页面 pages/login.vue
参照:Element ui Form表单
https://element.eleme.cn/#/zh-CN/component/form
校验利用策略模式, 和es5里的form表单验证思想一致
校验成功后, 调取登陆接口
submitLogin(){
var {pass,username} = this.ruleForm
axios({
method:‘post‘,
url:‘http://localhost:8081/api/login‘,
data:{
name:username,
password:pass
}
}).then((res)=>{
if(res.data.statusCode==200) {
alert(res.data.data);
localStorage.setItem(‘token‘,res.data.token); //用户访问页面的钥匙
this.$router.push({
path:‘/home‘
});
} else {
alert(res.data.data);
}
});
}
### 1.3 在home.vue页面调取相关接口 ,如何处理接口的多级回调
pages/home.vue
export default {
data(){
return {
name:‘laney‘,
params:this.$route.query,
infoData:{}
}
},
methods:{
getInfoList(){
var token = localStorage.getItem(‘token‘);
var test = {name:‘laney‘,age:‘20‘}
var mn = Qs.stringify(test);
// this.$axios.post(‘http://localhost:8081/api/info‘,mn).then((res)=>{
// console.log(‘test kkkk-----------‘);
// })
this.$axios({
method:‘post‘,
url:‘http://localhost:8081/api/info‘,
data:mn,
headers:{
token:token
}
}).then((res)=>{
if(res.data.statusCode==200) {
this.infoData = res.data.result;
var tag = res.data.tag;
return this.$axios({
method:‘post‘,
url:‘http://localhost:8081/api/msg‘
})
} else {
alert(res.data.result);
}
}).then((res)=>{
console.log(res.data.result)
});
}
},
mounted(){
this.getInfoList();
}
}
</script>
### 1.4 配置api
export default {
basic:{
login:‘/api/login‘,
info:‘/api/info‘,
msg:‘/api/msg‘,
hello:‘/api/hello‘
}
}
### 1.5 在入口文件main.js进行引入
import axios from ‘./providers/axios.js‘;
import api from ‘./providers/api.js‘;
//定义全局变量$axios
Vue.prototype.$axios = axios;
Vue.prototype.$api = api;
### 1.6 配置axios
yarn add axios -D , 已安装的可以忽略
引入axios
import axios from ‘axios‘;
导出的结构是:
export default {
post, //方法名
get,
pull
}
封装的目的:
1.需要把一些 api 的base路径配置好,以免多次重复写入
2.项目可能传递给接口的 数据 有json 和 formData 都需要考虑
3.对登陆后可能权限的 token需要获取 统一设置
4.对接口异常的情况需要统一处理
#### 1.6.1 第一种方式, 利用拦截器配置headers
后面讲
#### 1.6.2 第二种方式, 不利用拦截器配置headers
整体思路是在传参的时候, 可以多加一个参数form(true,false), true代表需要formData , false或者不选代表json
参考: axios2.js
var typearr= {
‘json‘:‘application/json;charset=UTF-8‘,
‘form‘:‘application/x-www-form-urlencoded‘
};
post (url, params) {
var isForm = params.form;
if(params.form) {
delete params.form;
}
if(isForm) {
params = Qs.stringify(params);
}
return new Promise((resolve,reject) => {
return axios.post(url,params, {
headers: {
‘X-API-TOKEN‘:localStorage.getItem(‘token‘),
‘Content-Type‘: isForm ? typearr[‘form‘] : typearr[‘json‘],
‘test‘:‘ppp‘
}
})
.then(response => {
if(response.status==200){
resolve(response.data);
}
//这里不需要异常提示了, 已经在拦截器设置
// else {
// Message({
// message: response.errorMsg,
// type: ‘warning‘
// });
// }
})
.catch(err => {
reject(err)
})
})
},
### 1.7在页面中使用
以news.vue为例
<script>
export default {
data(){
return {
infoData:{}
}
},
methods:{
getInfoList2(){
var res = this.$axios.post(this.$api.basic.info,{
kind:‘school‘,
form:true
}).then((res)=>{
console.log(res);
});
},
getInfoList(){
this.$axios.post(this.$api.basic.info,{
kind:‘school‘
},‘form‘).then((res)=>{
this.infoData = res.result;
if(res.tag==1){
return this.$axios.post(this.$api.basic.msg,{
tag:res.tag
})
}
}).then((res)=>{
if(res.kind==2){
return this.$axios.post(this.$api.basic.hello,{
id:res.kind
})
}
}).then((res)=>{
console.log(res.result);
})
}
},
mounted(){
this.getInfoList2();
// this.getInfoList();
}
}
</script>
### 1.8 拦截器的处理以及异常处理
var formData = new FormData();
formData.append(‘name‘,‘song‘);
formData.get(‘name‘);
//http request 拦截器 你给服务端 的数据
axios.interceptors.request.use(
config => {
config.headers.common = {
‘X-API-TOKEN‘: localStorage.getItem(‘token‘),
‘version‘: ‘1.0‘,
‘Content-Type‘: ‘application/json;charset=UTF-8‘
}
console.log(‘begin‘);
if (config.data.form) {
//转化成formData格式
// transformRequest只能用在 PUT, POST, PATCH 这几个请求方法
config.transformRequest=[function (data) {
//方式一
data.name=‘laney‘;
delete data.form;
var ret = ‘‘;
for (let it in data) {
ret += it+‘=‘ +data[it] + ‘&‘;
}
return ret.substring(0,ret.length-1);
//方式二:
// var test2 = Qs.stringify(data);
// return test2;
}]
}
return config;
},
error => {
return Promise.reject(err);
}
);
//响应拦截器即异常处理 - -- 服务给我们的数据
axios.interceptors.response.use(response => {
if (response.status === 200) {
return Promise.resolve(response);
} else {
return Promise.reject(response);
}
// return response
}, err => {
if (err && err.response) {
switch (err.response.status) {
case 400:
console.log(‘错误请求‘)
break;
case 401:
console.log(‘未授权,请重新登录‘)
break;
case 403:
console.log(‘拒绝访问‘)
break;
case 404:
console.log(‘请求错误,未找到该资源‘)
break;
case 405:
console.log(‘请求方法未允许‘)
break;
case 408:
console.log(‘请求超时‘)
break;
case 500:
console.log(‘服务器端出错‘)
break;
case 501:
console.log(‘网络未实现‘)
break;
case 502:
console.log(‘网络错误‘)
break;
case 503:
console.log(‘服务不可用‘)
break;
case 504:
console.log(‘网络超时‘)
break;
case 505:
console.log(‘http版本不支持该请求‘)
break;
default:
console.log(`连接错误${err.response.status}`)
}
} else {
console.log(‘连接到服务器失败‘)
}
return Promise.resolve(err.response)
})
然后开始封装函数
export default {
/**
* 封装post方法
* @param url
* @param data
* @returns {Promise}
*
*/
// 方式一: 包装一个 new Promise
// post (url, params) {
// return new Promise((resolve,reject) => {
// return axios.post(url,params)
// .then(response => {
// if(response.status==200){
// resolve(response.data);
// } else {
// alert(response.errorMsg);
// }
// })
// .catch(err => {
// reject(err)
// })
// })
// },
// 方式二: 包装一个 直接利用axios自身是一个Promise对象的思想封装
// post (url, params) {
// return axios.post(url,params)
// .then(response => {
// if(response.status==200){
// return Promise.resolve(response.data);
// //注意必须要有return,相当于new Promise里的resolve,告诉接口已经获取数据
// } else {
// alert(response.errorMsg);
// }
// })
// .catch(err => {
// reject(err)
// })
// },
//方式三
// 注意: axios在配置headers头的时候, 不要和上面的 拦截器重复配置
post (url, params) {
var isForm = params.form;
if(params.form) {
delete params.form;
}
if(isForm) {
params = Qs.stringify(params);
}
return axios({
method: ‘post‘,
url:url,
data: params
}).then((response) => {
if(response.status==200){
return Promise.resolve(response.data)
} else {
<!-- 如果设置了拦截器, 这里不需要做异常处理 -->
alert(response.errorMsg);
}
},(e) => {
return Promise.reject(e)
})
// 或者catch捕获异常
.catch(function (error) {
})
},
//方式四:
// async post (url, params,contype) {
// if(contype==‘form‘){
// params = Qs.stringify(params);
// }
// var res = await axios({
// method: ‘post‘,
// url:url,
// data: params
// });
// return res.data;
// },
get(url,params={}){
return new Promise((resolve,reject) => {
axios.get(url,{
params:params
})
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
},
}
### 1.9 异常消息提示
在axios.js里 添加
import { Message} from ‘element-ui‘;
然后直接使用
Message({
message: ‘提示信息‘,
type: ‘warning‘
});
## 一、 addRoutes的封装
//需要登陆后确认权限才能看到的路由
var asyncUser = [
{
path:‘/finance‘,
component:Finance,
meta: {
title: ‘财务信息‘,
roles: [‘admin‘]
}
},
{
path:‘/news‘,
component:News,
meta: {
title: ‘新闻中心‘,
roles: [‘admin‘,‘guest‘]
}
}
];
// 导航守卫 -- 全局前置守卫
routerAll.beforeEach((to,from,next)=>{
//这里可以获取登陆后的权限, 如果是admin
asyncUser = asyncUser.filter((item,index)=>{
return item.meta.roles.includes(‘guest‘)
})
//将新路由添加到路由中, 如果不加组件component不能正确渲染
routerAll.addRoutes(asyncUser);
//为了正确渲染导航,将对应的新的路由添加到routerAll中
routerAll.options.routes = [...routes,...asyncUser];
next();
})