说明
由于公司需要,我作为一个纯正的后端工程师,已经自学了半年多的vue了,愣是被逼成了一个小全栈,当然,小全栈这是往好听了说,事实上就是个前后端深度都不足的小菜鸡,在深知自己众多不足以及明白好记性不如烂笔头的道理下,多造轮子多做笔记总是不会错的:)
所以最近得空我把我刚学vuejs的时候写的烂工程重构了一下,重构的时候针对性的分模块做了一些笔记如下
- 路由
- 状态管理
- 权限管理
- 控件封装与使用
- 混入
- 数据模拟
- 打包优化与用户体验
如果不想拉这么长可以去 全球最大的同性交友网站 查看
进入烂笔头模式
路由
1. 路由加载
// 直接加载页面 |
2. 404路由
// 加载一个404页面 |
3. 路由拦截
// 路由跳转前的拦截器 |
4. 动态路由
动态路由一般配合页面级的权限控制使用
// 通过router.addRoutes方法动态添加可访问路由 |
5. 路由加载时动画
路由加载时的loading动画一般配合路由懒加载使用
// 在状态管理中定义一个路由loading标志 |
状态管理
1. 小知识
- state中的数据修改需要通过mutation或action触发
- mutation中的方法必须是同步函数
- action可包含任意异步操作,可返回一个Promise
- mutation以及action可以重复,调用时将会依次调用,getter必须唯一
2. 多模块
业务比较复杂时可使用状态管理中的多模块,有以下注意事项
- 除state会根据组合时模块的别名来添加层级,其他的都是合并在根级下,所以在回调函数获取的getters、commit、dispatch都是全局作用的
- mutation的回调参数只有state,state为当前模块的状态树,下同
- action的回调参数为state、rootState、getters、commit、dispatch,如果需要在action中调用其他的action可使用dispatch直接调用
- getter的回调参数为state、rootState、getters
- 模块间可以通过回调的rootState进行交互
- 出现重名的mutation、action将依次触发
// 多模块的实现 app以及user为各个子模块
export default new Vuex.Store({
modules: {
app,
user
},
getters
})
3. 辅助函数
Vuex除了提供了Store对象以外还对外提供了一些辅助函数
- mapState、mapGetters将store中的state、getters属性映射到vue组件局部的计算属性中
import { mapState } from 'vuex' |
- mapActions、mapMutations将store中的dispatch、commit方法映射到vue组件局部的方法中
import { mapActions } from 'vuex' |
4. 数据持久化插件
刷新页面时希望状态不被丢失时可用此插件
// 摘抄于 https://github.com/robinvdvleuten/vuex-persistedstate |
5. 日志插件
开发环境中希望能够跟踪状态变化并输出时可用此插件
// createLogger是vuex中的内置插件 |
权限管理
1. 需要实现的功能
- 根据用户登录后的权限表生成路由
- 页面级的权限控制
- dom元素级的权限控制
- 登录状态失效的处理
2. 路由设计
首先我们需要设计路由对象需要有哪些必要参数信息
为了实现权限管理我们必须要有roles参数代表该路由必须拥有哪些权限才能访问
为了更好的展示路由在这里设计了title、icon两个参数用于侧边栏的菜单展示
而有些路由不需要在侧边栏展示,这里使用hidden参数来告诉程序哪些路由是不需要展示的
// 首先设计路由对象参数 |
接下来我们需要实现路由的动态加载
系统初始化时加载必要路由,之后根据登录用户的权限加载符合条件的路由
// 定义系统初始化时加载的必要路由信息 |
3. 页面级的权限控制
使用路由拦截来实现页面级的权限控制
拦截路由跳转判断用户是否登录
从拉取的用户信息中提取权限表通过addRoutes方法动态加载异步路由表
每次路由跳转时判断用户是否拥有该路由的访问权限实现动态权限匹配
// 定义免登白名单 |
4. 元素级的权限控制
使用自定义指令来实现元素级的权限控制
在被绑定元素插入父节点时验证用户是否包含该元素的所需权限
根据鉴权结果来决定是否移除该元素
import store from '@/store' |
render函数
1. 如何封装一个支持render渲染的组件
- 首先创建一个函数式组件
// 表格拓展函数式组件的实现 |
- 在父组件中引入
// see https://github.com/calebman/vue-DBM/blob/master/src/components/table/table.vue |
- 使用render函数渲染
// see https://github.com/calebman/vue-DBM/blob/master/src/views/demo/datatable/data-table.vue |
混入
1. 小知识
- 混入对象将享有被混入组件的生命周期
- 数据对象混入冲突时将以组件数据优先
- 对象选项(如methods、components、directives)混入冲突时取组件对象的键值对
- 同名钩子混合为数组,混入对象的钩子将在组件自身钩子之前调用
2. 应用场景
- 希望部分路由页面在离开时销毁但是不希望每个路由页面都定义局部路由时
// 定义混入对象 |
- 数据表格自定义了文本、数字、时间以及文件单元格组件,每个组件都有同样的数据修改、焦点选中等方法时,可提取为混入对象,提高组件复用性
// see https://github.com/calebman/vue-DBM/blob/master/src/components/business/render-column-mixin.js |
- 希望降低组件的复杂度的时候可使用多个混入组件来分割核心组件的功能
# see https://github.com/calebman/vue-DBM/tree/master/src/components/table |
数据模拟
1. 需要实现的功能
- 拦截Ajax请求并延时响应
- 返回的统一的数据格式
- 响应不同的模拟数据
2. 配置Mockjs拦截Ajax请求
// see https://github.com/calebman/vue-DBM/blob/master/src/mock/index.js |
3. 响应的统一数据格式
// see https://github.com/calebman/vue-DBM/blob/master/src/mock/response.js |
4. 配置响应逻辑
// see https://github.com/calebman/vue-DBM/blob/master/src/mock/login.js |
5. 模拟随机数据
// see https://github.com/nuysoft/Mock/wiki |
打包优化
1. 做哪部分的优化
- cdn优化
- 路由懒加载
- 其他优化
- 用户体验
2. cdn优化
类似于vue、vue-router、moment、element-ui等提供了cdn的架或者工具类可在index.html中直接引入,然后配置webpack的externals使其不加入打包配置,从而减小app.js、vendor.js的体积
- 在index.html使用cdn引入依赖库
<!-- 网络请求工具类 --> |
- 配置build文件夹下webpack.base.conf.js文件
module.exports = { |
3. 路由懒加载
路由懒加载能够将代码根据路由配置进行分割,加快首屏渲染的速度,在大型的单页应用中是必不可少的
参见路由管理的实现
5. 其他优化
- 尽量少的注册全局组件,使用UI框架可以参考文档做按需加载
- 可以和服务端配合采用gzip压缩,减少传输耗时
- 在更新不是很频繁的应用可考虑提高缓存时间
- 例如moment、lodash这种庞大的工具库在使用的功能不多的情况下可考虑寻找替代品
6. 用户体验
一个单页应用到了一定规模不管怎么优化首屏渲染还是一个比较慢的过程,此时可以考虑在首屏渲染时使用一个加载动画告诉用户系统正在初始化
- 首先在index.html中定义一个渲染动画
<body> |
- 然后在App.vue组件的mounted钩子中移除这个loading
export default { |