项目环境
node : 12.10.0
npm : 6.10.3
vue-cli : 2.x
1、使用normalize.css统一浏览器标签样式
npm i -S normalize.css
main.js中引用:
import 'normalize.css'
2、使用reset-css重置默认样式
npm i -S reset-css
main.js中引用:
import 'reset-css'
3、引入iconfont图标库
这里我将阿里图标库放入到static/font目录下
main.js中引入:
import '../static/font/iconfont.css'
即可在vue中通过class="iconfont iconxxx"进行使用
4、使用vue-cookies管理cookies
npm i vue-cookies -S
main.js中
import vueCookies from 'vue-cookies';
Vue.use(vueCookies );
5、使用vue-router(cli已引入)
router目录下我的结构如下:
index.js // 路由入口文件
map // 路由
hooks // 路由钩子函数,用来鉴权
// index.js 路由入口文件,用于挂载路由和钩子 import Vue from 'vue'; import VueRouter from 'vue-router'; import routesMap from './map/'; // 路由映射(index.js) import hooks from './hooks/'; // 路由钩子(index.js) Vue.use(VueRouter); const router = new VueRouter({ mode: 'hash', routes: routesMap() }); hooks(router); export default router;
map/index.js
// map/index.js import home from './home'; // 删除没有权限的路由 function deleteNoAuth(arr) { // 自定义函数去遍历并删除没有权限的路由 } let routes = () => { let routes = [ ...home(), // 更多自己的路由 { path: "*", redirect: "/home/" } ]; deleteNoAuth(routes); return routes; }; export default routes;
map/home.js
// map/home.js // 懒加载(异步加载组件) const home = () => import('@/views/home/home.vue'); const routes = () => { return [ { path: '/home', name: 'home', flg: true, // 我自定义的权限命名 component: home, meta: { des: "首页" // 后续钩子函数动态改变title } } ]; }; export default routes;
hooks/index.js
hooks有以下文件及文件夹(beforeEach/afterEach/index.js)
hooks/index.js
import titleInterceptor from './beforeEach/titleInterceptor'; import authorization from './beforeEach/authorization'; // 这里仅介绍一下鉴权和动态改变title export default (router) => { router.beforeEach(titleInterceptor(router)); router.beforeEach(authorization(router)); };
hooks/beforeEach/authorization
// 登录权限 const authorization = (router) => (to, from, next) => { if (to.path == '/login') { next() } else { // 此处使用了vue-cookies,已经通过vue.use使用,所以可以直接使用,登录时设置了token字段 if (!router.app.$cookies.get('token')) { // 此处使用了element-ui中的message组件(element-ui使用这里省略) router.app.$message({ message: '登录身份过期,请重新登录!', type: 'warning' }) // 如无权限则回到login页面(请求权限将通过axios进行封装!) next('/login'); } else { next() } next() } }; export default authorization;
hooks/beforeEach/titleInterceptor
const titleInterceptor = (router) => (to, from, next) => { // 在路由中我使用meta.des设置title信息 const { meta, path } = to; document.title = to.meta.des || '今后宜喜。'; next(); }; export default titleInterceptor;
5、引入axios并封装请求
// 同样通过 npm i -S axios // 我在/src/http/index.js目录封装请求 import axios from 'axios'; import cookie from 'vue-cookies'; // axios全局配置 axios.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8'; // 添加请求拦截 axios.interceptors.request.use(function (config) { // 添加授权(通过vue-cookies在登录后设置token,这里将在后续请求中使用鉴权) if (cookie.get('token')) { config.headers['X-Authorization'] = "xxx " + cookie.get('token'); } return config; }, function (error) { return Promise.reject(error); }); // 添加响应拦截器 axios.interceptors.response.use(function (response) { return response.data; }, function (error) { if (error.response.status == 401) { // 授权不通过时,移除token并返回登录页 cookie.remove('token'); Router.push({ path: '/login' }); } return Promise.reject(error); }); export default axios;
前后端协同开发接口调用跨域问题,vue-cli可以方便的配置代理从而解决该问题:
在项目config/index.js目录中添加代理服务器地址,配置baseUrl:
// 在 dev对象下添加 proxyTable: { "/api": { target: "http://x.x.x.x:xxxx", // 设置你调用的接口域名和端口号 changeOrigin: true, pathRewrite: { "^/api": "" // 调用时使用url使用api/xxx即为http:x.x.x.x:xxxx/api/xxx } } },
vuex管理公共状态
npm i -s vuex
在src目录下创建store目录
store/index.js
import Vue from 'vue'; import Vuex from 'vuex'; // 引入定义的modules , 当然你可以定义单独的getters,mutations,state,这里仅定义modules/user用户信息用于说明 import user from './modules/user'; Vue.use(Vuex); const store = new Vuex.Store({ modules: { user } }); export default store;
store/modules/user.js
// 将vuex状态与localStorage结合从而实现状态持久化! var currentUser = localStorage.getItem("currentUser") && JSON.parse(localStorage.getItem("currentUser")); const state = { userInfo: currentUser ? currentUser : {} } const getters = { getUserInfo: state => { return state.userInfo } } // 这里通过localStorage将mutations数据做持久化处理,当然这里只是粗糙处理,可以单独封装函数用于统一将state保存到localStorage中(如果你的业务需要将state状态做持久化处理的话) const mutations = { setUserInfo(state, userInfo) { localStorage.setItem("currentUser", JSON.stringify(userInfo)); state.userInfo = userInfo }, clearUserInfo(state) { localStorage.removeItem("currentUser"); state.userInfo = {} } } const actions = { setUserInfoAsync({ commit }, user) { localStorage.setItem("currentUser", JSON.stringify(user)); commit('setUserInfo', user) } } export default { state, getters, mutations, actions }
main.js中:
import store from './store'; // ... new Vue({ el: '#app', router: router, store, components: { App }, template: '<App/>', })
总结
### 样式相关,使用了一下库统一浏览器样式,并使用iconfont normalize.css reset-css iconfont ### vue-cookies的使用 方便对cookies的操作,并且结合vue-router对路由进行鉴权,同时结合axios对请求进行鉴权 ### vue-router 钩子函数处理 ### axios的使用 对请求做统一处理,结合vue-cookies,vue-router进行鉴权。通过config/index.js设置proxyTable代理实现跨域请求。 ### vuex的使用 保存公共状态 # 具体依赖的使用可看npm下的readme进行实现