作为一名前端人员,并且作为一名使用过vue框架的前端人员,相信都听说过vue全家桶(1.项目构建工具vue-cli、2.路由vue-router:http://router.vuejs.org、3.状态管理vuex:http://vuex.vuejs.org、4.http请求工具axios:http://www.axios-js.com/zh-cn/docs/、5.样式element-ui:https://element.eleme.cn/#/zh-CN/component/installation、6.以及有时候后台没有提供接口需要自己模拟数据请求,我经常使用的mockjs)。为了方便与大家共同交流,特将自己搭建项目的方法记录下来。
之前已经分享过如何进行vue-cli 2.0安装及项目搭建,如果忘了,则可以去查看之前博客,在这里我就直接使用脚手架安装项目;
vue init webpack vue_all //默认安装即可,vue-router就已经安装整合到项目中
cd vue_all
npm run dev //运行项目即可
若自己想封装组件然后注册成全局组件,在components下创建base文件夹,存放需要注册至全局的组件,有mian.js文件中写如下代码:
// 引用公共组件
let componentFiles = require.context('./components/base', false, /\.vue$/)
componentFiles.keys().map((item, index) => {
let componentFile = item.replace(/^\.\/(.*)\.\w+$/, '$1');
let value = componentFiles(item)
Vue.component(`cui${componentFile}`, value.default)
})
1. npm i element-ui –save //安装element-ui插件
2. 在main.js文件中输入以下代码:
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
3. 若想按需引入组件,则可以按照element-ui官网进行相关插件安装,官网地址:https://element.eleme.cn/#/zh-CN/component/quickstart
4. 这里只是介绍简单项目搭建,若想更加深入的了解可去官网查看
以上即完成element-ui的安装,参考官网给出的组件与使用方法,在页面中需要的地方调用即可。
axios是promise实现的,提到promise,首先应该想到IE不支持,所以应该先加个垫片,给IE做下兼容性处理:
npm install --save babel-polyfill //安装es6转译组件
然后再main.js中引入 :
import 'babel-polyfill'
npm i axios --save
const context = require.context('./modules', false, /\.js$/);
const path=require("path")
let Api = {}
context.keys().map((m, k) => {
let strFileName = m.replace(/(.*\/)*([^.]+).*/ig,"$2");
let data=context(m).default;
Api[strFileName]=data
}, {})
export default Api;
config.js中的代码如下:
import axios from 'axios';
// 使用element-ui Message做消息提醒
import {Message} from 'element-ui';
// 创建实例时设置配置的默认值
/**
* 自定义实例默认值
*/
var instance = axios.create({
// baseURL: "/api", // 因为我本地做了反向代理
timeout: 10000,
// responseType: "json",
// withCredentials: true, // 是否允许带cookie这些
// headers: {
// "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
// }
});
// /api/getUserById
// 请求拦截器, 进行一个全局loading 加载,这种情况下所有的接口请求前 都会加载一个loading
/**
* 添加请求拦截器 ,意思就是发起请求接口之前做什么事,一般都会发起加载一个loading
* */
// 如果不想每个接口都加载loading ,就注释掉请求前拦截器,在http这个类中处理
instance.interceptors.request.use(
config => {
// 在发送请求之前做些什么(... 这里写你的展示loading的逻辑代码 )
isShowLoading(false);
// 获取token,配置请求头
// const TOKEN = localStorage.getItem('Token')
// 演示的token(注意配置请求头,需要后端做cros跨域处理,我这里自己前端配的跨域)
const TOKEN = '1fd399bdd9774831baf555ae5979c66b'
if (TOKEN) {
// 配置请求头 token
config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
config.headers['Authorization'] = TOKEN;
}
return config;
},
error => {
// 对请求错误做些什么,处理这个错误
// 可以直接处理或者展示出去,toast show()
console.warn(error);
// Message({
// // 饿了么的消息弹窗组件,类似toast
// showClose: true,
// message: error && error.data.error.message,
// type: 'error'
// });
Message.error(err.message)
return Promise.reject(error);
}
);
/**
* 添加响应拦截器,意思就是发起接口请求之后做什么事,此时只有两种情况,
* 要么成功,要么失败,但是不管成功,还是失败,我们都需要关闭请求之前的
* 发起的loading,那既然要处理loading,就把loading做成全局的了,
* 这里自定义一个处理加载loding 和关闭loading的方法,而且这个loading
* 要不要加载,会根据外部传入的布尔值来决定,默认是false:不展示
* */
instance.interceptors.response.use(
function (response) {
// 对响应数据做点什么
isShowLoading(false);
console.log(response)
// 根据你们家的后端定义请求过期后返回的参数,处理token过期问题
// 我这个接口木有token啊,这里演示下
// 判断
const {
status
} = response.data;
// 判断状态码401或者其它条件,不知道判断哪个的去问你家后台
// if (Object.is(status, 401)) {
// token过期后处理
// 1.删除你本地存储的那个过期的token
// 2. 跳转到登陆页(因为没有装路由,不写了,重新登陆赋值)
// todo...
// }
// 根据后端接口code执行操作
// switch(response.data.code) {
//处理共有的操作
// }
return response.data;
},
function (error) {
// 对响应错误做点什么
isShowLoading(false);
if (error && err.response) {
switch (err.response.status) {
case 400:
err.message = '错误请求'
break;
case 401:
err.message = '未授权,请重新登录'
break;
case 403:
err.message = '拒绝访问'
break;
case 404:
err.message = '请求错误,未找到该资源'
break;
case 405:
err.message = '请求方法未允许'
break;
case 408:
err.message = '请求超时'
break;
case 500:
err.message = '服务器端出错'
break;
case 501:
err.message = '网络未实现'
break;
case 502:
err.message = '网络错误'
break;
case 503:
err.message = '服务不可用'
break;
case 504:
err.message = '网络超时'
break;
case 505:
err.message = 'http版本不支持该请求'
break;
default:
err.message = `连接错误${err.response.status}`
}
} else {
err.message = "连接到服务器失败"
}
Message.error(err.message)
return Promise.reject(error);
}
);
// 如果与你配合的ui中,有loading组件的话,你直接用它的就可以了
// to do...
/**
* 是否开启loading
* @param {*} payload { type:Boolean }
*/
function isShowLoading(payload) {
// 获取dom节点
const loading = document.getElementById('loading');
payload ? loading.style.display = 'block' : loading.style.display = 'none';
}
/**
* 使用es6中的类,进行简单封装
*/
let http = {
// 使用async ... await
// static async get(url, params, isShow = false) {
// console.log(params)
// isShowLoading(isShow)
// return await instance.get(url, {
// params
// })
// }
// static async post(url, params, isShow = false) {
// console.log(params)
// isShowLoading(isShow)
// return await instance.post(url, params);
// }
// get请求
get(url, param = {}, isShow = false) {
isShowLoading(isShow)
return new Promise((resolve, reject) => {
instance.get(url, {
params: param
})
.then(res => {
resolve(res)
}, err => {
reject(err)
})
})
},
// post请求
post(url, param = {}, isShow = false) {
isShowLoading(isShow)
return new Promise((resolve, reject) => {
instance.post(
url,
param
).then(res => {
resolve(res)
}, err => {
reject(err)
})
})
},
// put请求
put(url, param = {}, isShow = false) {
isShowLoading(isShow)
return new Promise((resolve, reject) => {
instance.put(url, param)
.then(response => {
resolve(response)
}, err => {
reject(err)
})
})
},
// delete
delete(url, param = {}, isShow = false) {
isShowLoading(isShow)
return new Promise((resolve, reject) => {
instance.delete(url, param)
.then(response => {
resolve(response)
}, err => {
reject(err)
})
})
}
}
export default http;
modules文件夹下是各个模块的接口文件,goods.js文件是我写的一个demo文件,内容如下:
import http from "../config";
export default {
getGoods(params={}){
return http.get("/goods/getGoods",params)
}
}
二次封装完成后,在main.js文件中引入,将接口挂载到vue的原型方法上:
const Mock = require('mockjs');
Mock.mock('/goods/getGoods', 'get', () => {
return {
status: '0',
msg: '',
data: [{
_id:1,
productId: "201710003",
productName: "平衡车",
salePrice: 1999,
productImage: "pingheng.jpg",
productUrl: ""
}]
}
});
vuex是使用vue中必不可少的一部分,基于父子、兄弟组件,我们传值可能会很方便,但是如果是没有关联的组件之间要使用同一组数据,就显得很无能为力,那么vuex就很好的解决了我们这种问题,它相当于一个公共仓库,保存着所有组件都能共用的数据。一般情况下,vuex写在一个文件当中,但是当项目比较大的时候,容易造成数据耦合,为了方便维护,就需要将数据模块化。这里我介绍的模块化的封装:
import Vue from 'vue';
import Vuex from 'vuex';
import getters from './getters'
Vue.use(Vuex);
const modulesFiles = require.context('./modules', false, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
modules,
getters
});
export default store;
getters.js文件内容如下:
const getters = {
//getters 文件为导出state里面的数据,导出格式state => state.Login.userCode ,
//表示store/modules/Login/Login.js里面的state里的变量userCode
//如果不是很懂,下面会介绍在state存数据
goodsList : state => state.goods.goodsList ,
}
export default getters
mutations_type.js文件内容如下:
export const GOODS_GET = 'GOODS_GET';
export const GOODS_ADD = 'GOODS_ADD';
modules文件夹是vuex存放的各个模块的相关状态:
import * as mutationTypes from "../mutation_types.js"
const state={
goodsLength:0,
goodsList:[], //初始化一个userCode变量
};
// 赋值方法
const mutations={
[mutationTypes.GOODS_GET]: (state, device) => {//如何变化userCode,插入device
state.goodsList = device;
state.goodsLength=device.length?device.length:0;
},
};
//调用方法
const actions={
getGoods({ commit }, {$net,params}) {//触发mutations里面的userCodeChang ,传入数据形参device 对应到device
return new Promise((resolve,reject)=>{
$net(params).then(res=>{
commit(mutationTypes.GOODS_GET, res.data)
resolve(res)
}).catch(err=>{
reject(err)
})
})
},
};
export default {
namespaced:true,//用于在全局引用此文件里的方法时标识这一个的文件名
state,
mutations,
actions
}
mian.js文件中引入
// vuex的引入
import store from './store'
new Vue({
el: '#app',
router,
store,
components: {
App
},
template: ' '
})
在页面当中需要调用的地方,进行调用:
this.$store
.dispatch("goods/getGoods", {
$net: this.$api.goods.getGoods,
params: []
})
.then(res => {
debugger;
});
注意:
ie浏览器下[vuex] vuex requires a Promise polyfill in this browser.报这个错
需要安装babel-polyfill,
然后在webpack.base.conf.js中的entry配置[‘babel-polyfill’,’./src/main.js’]
以上只是将vue全家桶统一整合,方便开发vue项目使用,一人技短,众人技长,欢迎大家共同交流,后面遇到问题了,我也会不断修改此文档!