前几天和大家说要分享下前后端开发的经验,今天他来了!因为最近工作比较忙,内容也比较多需要分开几篇来讲,分享的内容不会有太深的理论东西,都是比较实用且简单易懂。作为第一篇分享先以前端开始,从项目创建到搭建基础架构,这块内容会比较多,所以会分开两篇或三篇,希望想学的朋友多些耐心哈,因为我也是抽时间一点点写,所以更新不会特别快,大概一周更新一到两篇吧,希望各位同学多多担待!
第一步,我们首先需要安装下环境,具体就不阐述了,这里需要注意一个点就是构建项目时有个区别需要讲一下,大牛请忽略!
vue init 和 vue create的区别:
vue create 是vue-cli3.x的初始化方式,目前模板是固定的,模板选项可自由配置,创建出来的是vue-cli3的项目,与cue-cli2项目结构不同,配置方法不同,具体配置方法参考官方文档。vue init 是vue-cli2.x的初始化方式,可以使用github上面的一些模板来初始化项目,webpack是官方推荐的标准模板名。vue-cli2.x项目向3.x迁移只需要把static目录复制到public目录下,老项目的src目录覆盖3.x的src目录(如果修改了配置,可以查看文档,用cli3的方法进行配置)
我这里是构建的是cli2.x版本,所以项目中很多配置都是cil2.x的配置方式,请大家注意下!
第二步,构建完成后我们启动下项目(有问题请自行百度,这个比较基础了),先把没有用的东西给干掉,然后引入ant-design-vue框架,npm install ant-design-vue --save,然后引入样式文件,这里有问题的同学可以参考antd官网
这里说一下,我是做的全局引入,没有做按需加载,我尝试了做按需加载有些问题,官网上找不到解决方案,需要自行百度,大概是JavaScriptEnabled的问题,如果做按需加载项目建议大家基于cli3.x进行搭建!
第三步,引入antd测试下没有问题的话我们开始配置路由守卫,我这里设置了一个丐版的,高配版大家根据自己需求调整就好
// 设置路由守卫,全局页面title修改
router.beforeEach((to, from, next) => {
if (to.meta.title) {
document.title = `VueDemo网站-${to.meta.title}`
}
const token = localStorage.getItem(ACCESS_TOKEN)
if (token) {
next()
} else {
if (to.meta.required) {
next({path: '/login'})
} else {
next()
}
}
})
我这里简单设置了一下当路由包含required且为true需要登录,所以我称之为丐版,正常项目中可以去设置自己的白名单来引入控制,或是包括一些权限的控制都在路由守卫里来完成,这里我通过localstorage来获取token,也可以引入Vue-ls插件来代替localstorage。
第四步,设置请求拦截,我把拦截器定义在router文件下了,新建一个request.js文件,我用的是axios来做请求拦截,先创建一个实例
import axios from 'axios'
import store from '../store'
import notification from 'ant-design-vue/es/notification'
import { ACCESS_TOKEN } from '../store/mutation-type'
const service = axios.create({
timeout: 6000
})
引入模块,然后定义请求和返回的响应机制,因为在请求接口之前先运行的就是拦截器,所以这里要写到位
// request发送请求配置
service.interceptors.request.use(config => {
const token = localStorage.getItem(ACCESS_TOKEN)
if (config.url.indexOf('http://127.0.0.1') === -1) {
if (token) {
config.headers['Authorization'] = 'bearer ' + token // 让每个请求携带自定义 token 请根据实际情况自行修改
}
config.headers['api-version'] = 'v1'
} else {
delete config.headers['api-version']
delete config.headers['Authorization']
}
return config
}, err)
// response 返回接受配置
service.interceptors.response.use((response) => {
if (response.config.responseType === 'blob') {
return response
}
return response.data
}, err)
// 定义错误异常
const err = (error) => {
if (error.response) {
const data = error.response.data
const token = localStorage.getItem(ACCESS_TOKEN)
if (error.response.status === 403) {
notification.error({
message: 'Forbidden',
description: data.message
})
}
if (error.response.status === 401 && !(data.result && data.result.isLogin)) {
if (token) {
store.dispatch('Logout').then(() => {
setTimeout(() => {
window.location.reload()
}, 1500)
})
}
}
}
return Promise.reject(error)
}
const blobAjax = (rUrl, method, callback, data) => {
const x = new XMLHttpRequest()
// x.open(method, process.env.VUE_APP_REQUEST_URL + rUrl, true)
x.open(method, rUrl, true)
x.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
x.responseType = 'blob'
if (localStorage.getItem(ACCESS_TOKEN)) {
x.setRequestHeader('Authorization', 'bearer ' + localStorage.getItem(ACCESS_TOKEN))
}
x.onload = function (e) {
const headers = x.getAllResponseHeaders()
// Convert the header string into an array
// of individual headers
const arr = headers.trim().split(/[\r\n]+/)
// Create a map of header names to values
const headerMap = {}
arr.forEach(function (line) {
const parts = line.split(': ')
const header = parts.shift()
const value = parts.join(': ')
headerMap[header] = value
})
callback(e, headerMap)
}
if (data) {
x.send(JSON.stringify(data))
} else {
x.send()
}
}
最后把拦截器暴露出来,后面可以直接在接口中进行使用
export {
service as axios,
blobAjax
}
我这里把下载的机制也写了下,也是之前项目中带的,顺手拿过来分享给大家
第五步,刚才定义拦截器大家看到了引入了vuex,其实vuex应该是先去做好的,我给忘记了,所以写在这里吧,安装步骤就不赘述了,直接说下使用:
首先,安装完之后定义一个store目录,这个目录用于存放瓶瓶罐罐,先给大家看下我的目录吧
在这里我把仓库细分开来了,user作为用户状态单独管理,后期如果有其他模块需要进行管理的状态在进行单独定义即可。
其次,定义好store目录后创建一个index文件,我们都知道vuex核心的点就是state,getters,actions,mutations,modules组成:
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import getters from './getters'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
user
},
mutations: {
},
actions: {
},
getters
})
state:Vuex使用来存储应用中需要共享的状态。为了能让 Vue 组件在更改后也随着更改,需要基于state创建计算属性。
getters:类似于 Vue 中的 计算属性(可以认为是 store 的计算属性),getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
actions:actions并不能直接更改state的状态,它通过调用mutations来进行更改,通常在使用的时候是通过参数解构的方式调用commit来进行修改操作,actions处理异步方式可以参考官网或项目代码。
mutations:mutations可以说是actions的执行者,获取actions需要修改的内容。
modules:基于项目实际情况考虑,如果项目较大,且管理状态的内容较多,建议将store分割,使每个模块都独立拥有getters、actions、mumations、actions,便于管理。
import { ACCESS_TOKEN, USER_INFO } from '@/store/mutation-type'
import api from '../../api/login'
const user = {
state: {
info: {},
token: '',
},
mutations: {
SET_TOKEN (state, token) {
state.token = token
},
SET_USER_INFO (state, info) {
state.info = info
}
},
actions: {
Login ({commit}, userInfo) {
return new Promise ((resolve,reject) => {
api.login(userInfo).then(response => {
if (response.code == 0) {
localStorage.setItem(ACCESS_TOKEN, response.data.accessToken)
localStorage.setItem(USER_INFO, response.data.user)
commit('SET_TOKEN', response.data.accessToken)
commit('SET_USER_INFO', response.data.user)
resolve()
} else {
reject(response.data.message)
}
}).catch(error => {
reject(error)
})
})
},
Logout ({commit},state) {
return new Promise(resolve => {
commit('SET_TOKEN','')
commit('SET_USER_INFO',{})
localStorage.removeItem(ACCESS_TOKEN)
localStorage.removeItem(USER_INFO)
resolve()
})
}
}
}
export default user
以上便是vuex的核心知识点,说实话,我只会用,了解基本原理概念,太深入的东西我也没有去研究,仓库这里确实不是很好理解,以前没有做大型项目的时候基本用不到,所以长期以来vuex可以说是vue全家桶的短板吧,自此我也总结了下学习方法,那就是不会的东西,先找个参考去写,多写几遍,然后再去官网看资料,然后再去研究自己写的,自然而然就会了,当然了,这个是笨办法。
自此一个项目的简单架构便搭建完成了,整个项目的重点:1.请求拦截器;2.路由守卫;3.vuex仓库管理,希望各位同学在实践的时候一边看官网,一边找参考去理解。
其实在实际项目开发中,这些工作一般都有架构师去做,即使没有架构师,网上也有很多的成熟架构供使用。当然了,用别人的和自己会造还是两码事
下一篇将讲述如何配置架构的相关文件,敬请期待...
git地址:https://gitee.com/jacky_201314/vue_antd_infrastructure