@vue/cli3+typescript项目实战之给无限级嵌套的导航添加激活样式(上)
0
阅: - 评:0 - 积分:摘要:由于无限级嵌套导航比较复杂,所以打算分三篇来写。这一篇主要先实现一级导航菜单,然后优化代码,最后通过路由前置守卫实现动态修改路由对应页面的标题title......
一、前言
书接上回《@vue/cli3项目实战之后端返回动态路由后前端使用router.addRoutes无效?》,在上一篇文章中留下了一个疑问:如何给导航排序呢?不知各位看官有没有思考这个问题。
routes
是一个数组,所以这个问题可以采用:再定义一个key,通过比较其值大小的方式来实现,比如上篇文章中定义的id。当然了,这个id还有其他用途!
本来打算一篇文章写完无限级嵌套导航的,考虑到实现激活样式的繁琐以及此功能可以演变成很多种不同场景,所以本文将会一分为三。我们从最基础的一级导航开始,然后再讲二级导航,最后通过二级导航引出无限级导航菜单。
看官们准备好了吗?咱们开始吧。
二、先实现普通的一级导航
2.1、@vue/cli创建项目
此处以@vue/cli3为例,若看官使用的是vue-cli 2
,请移步于vue/cli官网查看更多。
准备工作:
1、在我们日常工作目录中右键;
2、然后点击Git Bash Here
;
3、接着输入:winpty vue.cmd create recursive-navigation
并回车;
4、按上下方向键选择一个自己常用的模板,例如:typescript模板,选择后按下回车键。
稍等片刻后,当命令窗口中出现Successfully created project recursive-navigation
时就表示项目就已经创建完毕了。
- recursive-navigation 项目目录
- public # 静态资源目录
- img # 图片
- favicon.ico # 网站图标
- index.html # html模板
- robots.txt # 爬虫协议
- src # 资源目录,基本上开发过程中都在此目录下进行
- assets # 静态资源
- components # 组件目录
- router # 路由目录
- index.ts # 路由配置文件
- store # vuex状态管理目录
- index.ts # store配置文件
- views # 相关页面
- About.vue # about页面
- Home.vue # home页面
- App.vue # 启动页面
- main.ts # 入口文件
- shims-tsx.d.ts # 允许.tsx 结尾的文件,在 Vue 项目中编写 jsx 代码
- shims-vue.d.ts # 主要用于 TypeScript 识别.vue 文件,Ts 默认并不支持导入 vue 文件
- .browserslistrc # 可以理解为配置的css兼容性(用于支持 Autoprefixer)
- .eslintrc.js # eslint配置
- .gitignore # 忽略要提交的git文件
- babel.config.js # babel-loader配置
- package.json # package 配置
- package-lock.json # 锁定package 配置
- README.md # 描述文件
- tsconfig.json # typescript 配置
- node_modules # 包管理
- .git # git目录
上面的目录及文件全都是自动生成的,下面我们来做些修改。
2.2、新增后的目录结构:
- recursive-navigation 动态路由目录
- package.json # 此文件有修改
- src
- App.vue # 此文件有修改
- router # 此目录下有新增文件
- list.ts # 路由
- index.ts # 有修改
- views # 此目录下有新增文件
- PageA.vue # PageA页面
- PageB.vue # PageB页面
- PageC.vue # PageC页面
- ...... 其他目录及文件暂时不做修改
2.3、修改package.json文件,自动启动浏览器
截止目前为止,咱们通过@vue/cli3脚手架创建的项目在执行npm run serve
命令后需要手动打开浏览器,这种用户体验是非常不好的!所以,我们来改进下代码,让其自动启动浏览器。
在vs code或其他编辑器中打开package.json
文件,通常情况下应该是第6行。或者直接搜索:"serve": "vue-cli-service serve"
,然后做如下修改。
- "serve": "vue-cli-service serve", /* 修改前长这样 */
- "serve": "vue-cli-service serve
--open
", /* 修改后的 */
注意黄色高亮部分,只添加了一个--open
属性。现在我们切换到git窗口,输入npm run serve
并回车。此时,神奇的一幕就出现了哈!麻麻再也不用担心我要手动复制网址了。
2.4、分离路由文件
为了更好的管理我们的路由,此时我们需要对router/index.ts
做些修改,主要是把routes
单独放一个文件夹中。
- import Vue from 'vue'
- import VueRouter, \{ RouteConfig \} from 'vue-router'
- import navList from './list' /* 导入路由列表 */
- Vue.use(VueRouter)
- const routes: Array<RouteConfig> = [] /* 清空原来的 */
- routes.push(...navList) /* 把路由添加进来 */
- const router = new VueRouter({
- mode: 'history',
- base: process.env.BASE_URL,
- routes
- })
- export default router
友情提示:上面代码中的\
反斜线是为了防止在文章中转码,看官复制后替换为空即可。
注意上面有三处黄色高亮的代码,我们通过import
导入了一个文件,然后又清空了原来的routes
数组,接着在下方通过push
向routes
追加数据。
至于router/list.ts
中的内容,看官应该能猜出个一二吧。
- import Vue from 'vue'
- import \{ RouteConfig \} from 'vue-router'
- import Home from '../views/Home.vue'
- const navList: Array<RouteConfig> = [
- {
- path: '/',
- name: 'Home',
- component: Home
- },
- {
- path: '/about',
- name: 'About',
- component: () => import(/* webpackChunkName: "About" */ '../views/About.vue')
- },
- {
- path: '/pageA',
- name: 'PageA',
- component: () => import(/* webpackChunkName: "PageA" */ '../views/PageA.vue')
- },
- {
- path: '/pageB',
- name: 'PageB',
- component: () => import(/* webpackChunkName: "PageB" */ '../views/PageB.vue')
- },
- {
- path: '/pageC',
- name: 'PageC',
- component: () => import(/* webpackChunkName: "PageC" */ '../views/PageC.vue')
- }
- ]
- export default navList
友情提示:上面代码中的\
反斜线是为了防止在文章中转码,看官复制后替换为空即可。
至此,现在路由中有5条数据了。
上面的PageA.vue
、PageB.vue
、PageC.vue
这三个可以通过复制About.vue
改名可得,里面没什么内容,简单修改即可,此处就不写了。
2.5、修改App.vue文件
接下来,我们修改App.vue
文件,让路由出现在页面上。
- /* 代码修改前 start */
- <div id="nav">
- <router-link to="/">Home</router-link> |
- <router-link to="/about">About</router-link>
- </div>
- /* 代码修改前 end */
- /* 代码修改后 start */
- <div id="nav">
- <router-link to="/">Home</router-link> |
- <router-link to="/about">About</router-link> |
- <router-link to="/pageA">PageA</router-link> |
- <router-link to="/pageB">PageB</router-link> |
- <router-link to="/pageC">PageC</router-link> |
- </div>
- /* 代码修改后 end */
现在切换到浏览器可以看到页面上显示了5个导航菜单。如图:
至此,我们的一级导航功能算是实现了。从头到尾,没有任何难点儿。
2.6、优化之路
那我们是否可以优化下代码呢?答案是肯定的。
2.6.1、抛出问题:每创建一个路由,需要修改哪些内容?
要想解决问题必须要先了解问题,如果不能了解问题,那就谈不上解决了。通过前面的步骤不难发现,每新增一个路由时需要修改3个地方,分别是:
1、list.ts;
2、新增对应的page页面;
3、修改App.vue页面中的router-link
那有没有可以省略的地方呢?
2.6.2、分析问题:分析每一步是否可省
首先,list.ts
是肯定不能省略的,这要是省略了,那还怎么新增路由?
其次,关于对应的page页面,如果是复用的话倒是可以省略。
最后,这个App.vue
页面需要手动新增router-link
,这也太不人性化了吧!
所以,我们需要对App.vue
动手。
2.6.3、解决问题
通过router.options.routes
可以获取路由数据,然后通过v-for
循环的方式循环router-link
就完事儿了。
- /* 代码修改前 start */
- <div id="nav">
- <router-link to="/">Home</router-link> |
- <router-link to="/about">About</router-link> |
- <router-link to="/pageA">PageA</router-link> |
- <router-link to="/pageB">PageB</router-link> |
- <router-link to="/pageC">PageC</router-link> |
- </div>
- /* 代码修改前 end */
- /* 代码修改后 start */
- <div id="nav">
- <router-link v-for="(item, index) in $router.options.routes" :key="index" :to="item.path">\{\{item.name\}\} | </router-link>
- /* 代码修改后 end */
友情提示:上面代码中的\
反斜线是为了防止在文章中转码,看官复制后替换为空即可。
保存后在前台页面上是看不出任何变化的,虽然我们已经优化了代码。[:笑哭]
三、修改页面title
此时我们点击任意导航,浏览器上的title
始终没有跟随变化。显然,这对SEO优化而言是非常不利的。
那要怎么搞呢?要是传统的项目,咱们直接找到对应的html页面,修改title
标签中的内容即可。但现在是Vue项目,全局只有一个index.html
模板文件,硬改肯定是不行的。
3.1、修改router/list.ts文件
由于我们在router/list.ts
文件中定义了每个页面的路由信息,所以理应title
设置也一起设置。vue官方提供了meta
字段,详情请访问→→路由元信息,所以我们可以把title
添加进meta
中。
- ...... /* 原代码未做修改 */
- const navList: Array<RouteConfig> = [
- {
- path: '/',
- name: 'Home',
- component: Home,
- meta: {
- title: '首页'
- }
- },
- {
- path: '/about',
- name: 'About',
- component: () => import(/* webpackChunkName: "About" */ '../views/About.vue'),
- meta: {
- title: '关于我们'
- }
- },
- {
- path: '/pageA',
- name: 'PageA',
- component: () => import(/* webpackChunkName: "PageA" */ '../views/PageA.vue'),
- meta: {
- title: '页面A'
- }
- },
- {
- path: '/pageB',
- name: 'PageB',
- component: () => import(/* webpackChunkName: "PageB" */ '../views/PageB.vue'),
- meta: {
- title: '页面B'
- }
- },
- {
- path: '/pageC',
- name: 'PageC',
- component: () => import(/* webpackChunkName: "PageC" */ '../views/PageC.vue'),
- meta: {
- title: '页面C'
- }
- }
- ]
- export default navList
友情提示:上面代码中的\
反斜线是为了防止在文章中转码,看官复制后替换为空即可。
保存代码后刷新页面,你会发现什么变化都没有,跟刚才没修改前一模一样![:笑哭]
懵逼不?不用怀疑代码写错了,因为步骤还没有完!
3.2、“全局前置守卫”登场
之所以页面标题没有跟随路由发生变化是因为我们没有进行手动干预!我们可以通过官方提供的router.beforeEach
对要跳转的路由进行拦截并干点儿其他的事情。详情请访问导航守卫
- ...... /* 以上代码未做修改 */
- const router = new VueRouter({
- ...... /* 此处代码未做修改 */
- })
- router.beforeEach((to: Route, from: Route, next: NavigationGuardNext<Vue>) => {
- if (to.meta) {
- document.title = to.meta.title || '无标题' /* 动态设置页面标题 */
- }
- next()
- })
- export default router
现在,我们再点击页面上的导航菜单可以看到浏览器地址栏前的title已经跟随页面发生了变化。
如图:通过全局前置守卫来修改页面的title.gif
四、demo源码
本篇源码已上传到了github
上的dev-recursive-navigation-1-20200719
分支中。如果看官需要研究源码,可以点击下面的链接进行访问并下载。
- 网址: 戳我前往github查看源码
转载声明:
若亲想转载本文到其它平台,请务必保留本文出处!
本文链接:/xwzj/2020-07-19/vue-cli3-recursive-navigation-1.html
若亲不想直保留地址,含蓄保留也行。艺灵不想再看到有人拿我的技术文章到他的地盘或者是其它平台做教(装)程(B)而不留下我的痕迹。文章你可以随便转载,随便修改,但请尊重艺灵的劳动成果!谢谢理解。
亲,扫个码支持一下艺灵呗~
Tag: @vue/cli3 vue项目实战 路由守卫 router.beforeEach typescript 路由 router cli脚手架 路由懒加载 嵌套路由
上一篇: @vue/cli3项目实战之后端返回动态路由后前端使用router.addRoutes无效? 下一篇: 移动端页面适配之iPhoneX的安全区域