前言
上一章已经搭好了基本的vue项目,现在来对他进行拓展吧。
一、vue全家桶
在之前的步骤中,我们的项目vue全家桶只装了vue-router,接下来我要将全家桶剩下的家人都安装下去,同时对他们进行一点点改动。
1、vue-router
这是默认创建的router文件夹,router的所有内容都在index.js里面。在之后的应用中,我们需要在路由中设立守卫,判断是否退回登录页、无页面是否跳转404,同时路由的列表也写在这里会显得臃肿,不好阅读。所以在统一级文件夹下创建一个"routes"文件夹来专门存放路由列表,而index则存放路由守卫的行为
创建routes.js文件,并把路由列表填上
import HelloWorld from '@/components/HelloWorld'
const menuRouter = [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
export default menuRouter
在index.js中引入,同时写上路由守卫。
import Vue from 'vue'
import Router from 'vue-router'
import routes from './routes'
// import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
// export default new Router({
// routes: [
// {
// path: '/',
// name: 'HelloWorld',
// component: HelloWorld
// }
// ]
// })
const createRouter = () => new Router({
scrollBehavior: () => ({ y: 0 }), //滚动条置0
routes: routes
})
const router = createRouter()
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
/*防止重复点击导航报错*/
return originalPush.call(this, location).catch(err => err)
}
router.beforeEach((to, from, next) => {
/* 必须调用 `next` */
const flag= true
if (!flag && to.path !== '/login') {
return next({ name: 'login' })
}
if (flag && to.path === '/login') {
return next({ name: 'home' })
}
return next()
})
router.afterEach((to, from, next) => {
if (to.matched.length === 0) {
router.push({ path: '/404' })
}
})
export default router
到这里vue-router暂时配置成这样,之后添加路由则到routes.js配置,添加登录状态判断或者其他路由配置,则到index.js中配置。
2、vuex
npm install vuex --save
或者yarn add vuex --save
安装完成后,创建一个"store"文件夹,把index.js放进去。同样的,我们需要使用vuex保存各种状态。
例如:登录用户的各种状态、信息,项目所需要的各种状态、信息,甚至可以把字典放进去。这里我们分两个出来,一个放用户的,一个放项目的。
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import user from './modules/user'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {app,user}
})
export default store
//modules下app.js
const app = {
state: {
appLoading: {
tip: '加载中',
loading: false
},
navList: []
},
mutations: {
setAppLoading (state, data) {
state.appLoading = { ...state.appLoading, ...data }
},
setNavList (state, payload) {
state.navList = payload
}
}
}
export default app
const user = {
namespace: true,
state: {
token: null,
userInfo: null,
departmentList: null
},
mutations: {
setToken (state, token) {
state.token = token
},
// 设置用户信息
setLoginUser (state, loginUser) {
state.userInfo = loginUser
// location.reload()
},
// 设置用户部门信息
setUserDepartment (state, data) {
state.departmentList = data
}
},
actions: {
// 登录
async login ({ commit, state }, data) {
const res = {data: {name: 'zz'}} // 登录接口
if (!res) {
return false
}
commit('setLoginUser', res.data)
return true
},
async logout ({ commit, state }, data) {
// 登出接口
commit('setToken', '')
commit('setLoginUser', '')
commit('setUserDepartment', [])
},
// 获取用户部门list
async getUserDepartment ({ commit, state }, data) {
const res = null // 获取部门接口
if (!res) {
return false
}
commit('setUserDepartment', res.data)
}
}
}
export default user
创建好后,在main.js中引入vuex
import store from './store'
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
这就配置完成了,我们在HellowWorld中试一下吧
<template>
<div class="hello">{{ msg }}
<button @click="login">登录</button>
<button @click="changeMsg">store改变msg</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
computed: {
getUserInfo () {
return this.$store.state.user.userInfo
}
},
methods: {
login () {
this.$store.dispatch('login', '')
},
changeMsg () {
this.msg = this.getUserInfo ? this.getUserInfo.name : 'null'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
当vuex中没有用户的name时,点击改变信息将会返回null。而登录后改变了vuex的状态,这时候点击改变信息按钮,将会返回vuex中的用户名
vuex拓展
在这里你会发现一个问题,就是当你刷新页面以后,vuex里存储的数据就都没了,我们有两种方法可以解决,一种是存储在浏览器缓存里面,一种是重新请求接口获取,甚至可以把这两种方法合起来。这里我用vuex-persistedstate插件帮我存储。
3、axios
npm install axios -g
或者用yarn也行。
对于请求,我们需要做一些拦截和配置。例如发送前所需的配置以及加密,发送后的拦截,常见的600无登录跳转登录页处理,默认的错误处理等等。我们创建一个utils文件夹,存放各种工具,然后创建一个request.js来处理axios。
import axios from 'axios'
import store from '../store'
const reqArr = []
const reqStart = (config) => (config.loading && reqArrProxy.push(config))
const reqEnd = (res) => reqArrProxy.pop()
const reqArrProxy = new Proxy(reqArr, {
get: function (target, key, receiver) {
return Reflect.get(target, key, receiver)
},
set (target, key, value, receiver) {
if (key === 'length' && value === 0) {
store.commit('setAppLoading', { loading: false })
} else {
store.commit('setAppLoading', { loading: true })
}
return Reflect.set(target, key, value, receiver)
}
})
// 创建一个AXIOS实例 (请求不同服务器地址或超时时长等等可以创建不同的实例)
const request = axios.create({
withCredentials: true, // 跨域请求时发送cookies
timeout: 1000 * 30 // 请求超时
})
// config 代表发起请求的参数的实体
request.interceptors.request.use(
config => {
reqStart(config)
config.baseURL = config.baseURL || window.baseURL || 'api'
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
return config
},
error => {
return Promise.reject(error)
}
)
// 请求到结果的拦截处理
request.interceptors.response.use(
response => {
reqEnd(response)
const { data } = response
if (data.code === '200' || data.code === '911') {
return data
} else if (data.code === '600') {
// 未登录或登录过期
// 进行返回登录页的操作
return false
} else {
// 其他错误操作
return false
}
},
error => {
// 请求错误需要自行处理
console.info(error)
reqEnd(error)
if (error.config.isHandleError && error.config.isHandleError === true) {
return error
} else {
return false
}
}
)
export default request
之后引入他就能够使用了
import request from "@/utils/request.js"
export const loginUser = (data) => request({
url: "url",
method: "POST",
data
})
总结
全家桶大概就到这里了,有什么写错的地方接受批评,有补充的地方大家一起交流交流。漫漫前端路,大家一起努力吧。