✨ 高扩展性能路由
往期的博客已经记录了一部分的路由router相关的博客,大家感兴趣的可以去主业去了解一下我们的路由的相关知识,这里就不进行大的扩展了,我们直接进入我们的主题。我们应该怎么设计一个高扩展性能的路由呢?
我们知道路由一般有两种方案,第一种是基于我们的配置的,另一个就是基于我们自己本身写代码的程序猿自己约定的,约定就是第三方轮子提供的工具暗战其规范生成的路由的配置。
操作的步骤,我们先实现注册以及登录,回到我们的router下面,显示定义一个路径,文件下面是我们的子路由,组件之间的话我们可以采用异步加载的方式,这里的webpack其实就是把我摁的相同的名字的打包在一起,第二个就是我们的注册页的register。
相应的我们回到我们的view下面新建一个user,回到我们的路由,user其实也应该是一个指定的一个组件,用于放router-view,不然的话我们下面就会跳不过去,前往我们的component下面简单一个renderrouterView组件,我们将这组件放到路面就可以了。
因为我们的template和我们的jxs到最后面都会转换成为我们的render函数。
实例代码:
const router = new Router({ routes: [ { path: '/', redirect: '/login' }, { path: '/login', component: Login }, { path: '/home', component: Home, redirect: '/welcome', children: [{ path: '/welcome', component: Welcome }, { path: '/users', component: Users }, { path: '/rights', component: Rights }, { path: '/roles', component: Roles }, { path: '/categories', component: Cate }, { path: '/params', component: Params }, { path: '/goods', component: GoodsList }, { path: '/goods/add', component: Add }, { path: '/orders', component: Order }, { path: '/reports', component: Report } ] } ] })
那页面的布局就单独再建一个 layouts 文件夹,下面写一些简 单的信息外加一个 router-view,则 user 那里也不需要 render 函数了,直接调用这个布局组件,最终打包到 layout 那。当 然也可以在子组件那加多一个重定向。 剩下的路由差不多就直接复制过来。
// 挂载路由导航守卫 router.beforeEach((to, from, next) => { // to将要访问的路径 // from 代表从哪个路径跳转而来 // next是一个函数,表示放行 // next() 放行 next('/login')强制放行 if (to.path === '/login') return next() // 获取token const tokenStr = window.sessionStorage.getItem('token') if (!tokenStr) return next('/login') next() }) export default router
将对应的组件建立起来,包括 BasicLayout(引入使用后面三的其他的组件)、Header.vue、Oreder.vue、Right.vue等等其他剩下的组件。 在 views 下面建一个 Dashboard 文件夹,下面丢 Analysis.vue, 再建一个 Forms,下面建一个 BasicForm.vue、StepForm 文件 夹下面建一个 index.vue 提供一个挂载点(router-view),再 建 step123. 最后是什么都匹配不到的路由给个*,新建一个 404.vue,找 不到就调用这个组件即可。 我们希望路由发送跳转的时候可以给用户一个友好的提示, 一个动画,所以可以安装一个 nprogress 库。在 router.js 中引 入该库和该库下面的样式。 那么在哪里使用?其实路由切换时都会通过一个钩子即路 由守卫,可以在里面做逻辑,不过就不能直接 import default 把路由导出去了,需要用一个变量保存,然后导出这个变量。 导出之前调用其 beforeEach,接收三个参数:to、from、next (to 是要去的路由,from 是当前路由,next 是做完逻辑必须 调用它才能往下走),里面调用库的 start 方法然后 next 就行, 再调用 afterEach,里面调用库的 done 方法即可。
✨ 高扩展性能路由
copy 一个单文件递归菜单(因为菜单可能有很多级),注意 需要注意单文件递归的使用规范。 拷贝到 SliderMenu 直接替换,还需要再建立一个单独的文件 SubMenu.vue,毕竟是要用来做递归,推荐是函数式组件(直 接去下载),然后就在 main.js 注册。按钮是不需要了,可以 去掉,主题的话也可以用 props 来接收 theme,当然 Basic 调 用的时候也记得传过去。到此就实现了一个简单的菜单,不 过目前只是文档的示例 mock 数据。 我们想要使用自己的数据,通过路由去实现,可以看到路由 也是一个递归的,当然有一些是不需要渲染上去的,我们可 以添加一个标志位 hideInMenu 布尔值到 user 和 404 就不要 渲染了。约定一下,渲染的时候有 name 就作为菜单,没有 就继续往下一层。
我 们 不 想 子 路 由 也 渲 染 上 去 所 以 再 加 一 个 hideChildrenInMenu 标志位,虽然是不渲染,但是如果访问 的是我们这个子路由还是希望菜单显示在对应上一级的菜 单。然后路由还可以再加多一个字段 meta 对象作为对菜单 的描述包括 icon(库里有的图标且在一级菜单)和 title。 设置完成路由后回到 SliderMenu 来设置原始的数据,定义一 个方法 getMenuData,接受参数 routes,data 里面的 list 就可 以置空了,通过 this.$router.options.routes 拿到路由配置保存
为 menuData 变量(当然也可以从 router.js 那抛出,都行), 再定义一个空数组,对参数即路由配置进行遍历,如果是 name 存在且没有 hideInMenu 则解构出来给 newItem(不改 变原数据)删除其 children,如果是有子项了且没有隐藏子 项菜单就递归获取一次数据给 children,把 children 传进去, 最后将新数组 push 到变量,如果不是隐藏菜单也不隐藏子 菜单且存在子菜单就递归这个方法传入 children 解构再推到 数组。
将 list 换成我们的 menuData 进行渲染,key 是 path,改变图 标(需要判断是否存在图标)和 title,subMenu 组件也是更 改相应的图标与文字。到此就完成了菜单。 接下来是让菜单和路由联动起来,需要注意 menu 标签里面 的 key(带 default 是第一次加载的时候会使用,以后不管怎 么样都无法再改变这个值,可以用在一些无需关心的内容上, 相当于是写死值),去掉 default,与我们的 router 关联起来。 在 data 中定义对应的两个 key 变量数组:selectedKeys 和 openKeys,在外面定义对应的两个 map 空对象,方法传入两 个 keys,注意这个 parentkeys 的话是从头到尾储存的,如果 没有就给个空数组,selectedKesy 是给当选中公共表单的父 级菜单,其具体的一二级等表单不显示就指定到这。 监听$router.path,如果更改了则改变我们对应的 key,当然 openKeys 需要判断是否打开了菜单再说,初始值也是。
路由挂钩的话是给每一个菜单项标签加一个点击事件,通过 $router.push 实现点击菜单跳转到对应的页面,子组件前面多 加一个 parent,当然 query 需要保留下来,关闭就交给 layout 去搞,openKeys.sync 实现双向绑定