艺灵设计

全部文章
×

@vue/cli3+typescript项目实战之给无限级嵌套的导航添加激活样式(上)

作者:艺灵设计 - 来源:http://www.yilingsj.com - 发布时间:2020-07-19 23:00:40 - 阅: - 评: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时就表示项目就已经创建完毕了。

  1. recursive-navigation 项目目录
  2.   public # 静态资源目录
  3.     img # 图片
  4.     favicon.ico # 网站图标
  5.     index.html # html模板
  6.     robots.txt # 爬虫协议
  7.   src # 资源目录,基本上开发过程中都在此目录下进行
  8.     assets # 静态资源
  9.     components # 组件目录
  10.     router # 路由目录
  11.       index.ts # 路由配置文件
  12.     store # vuex状态管理目录
  13.       index.ts # store配置文件
  14.     views # 相关页面
  15.       About.vue # about页面
  16.       Home.vue # home页面
  17.     App.vue # 启动页面
  18.     main.ts # 入口文件
  19.     shims-tsx.d.ts # 允许.tsx 结尾的文件,在 Vue 项目中编写 jsx 代码
  20.     shims-vue.d.ts # 主要用于 TypeScript 识别.vue 文件,Ts 默认并不支持导入 vue 文件
  21.   .browserslistrc # 可以理解为配置的css兼容性(用于支持 Autoprefixer)
  22.   .eslintrc.js # eslint配置
  23.   .gitignore # 忽略要提交的git文件
  24.   babel.config.js # babel-loader配置
  25.   package.json # package 配置
  26.   package-lock.json # 锁定package 配置
  27.   README.md # 描述文件
  28.   tsconfig.json # typescript 配置
  29.   node_modules # 包管理
  30.   .git # git目录

上面的目录及文件全都是自动生成的,下面我们来做些修改。

2.2、新增后的目录结构:

  1. recursive-navigation 动态路由目录
  2.   package.json # 此文件有修改
  3.   src
  4.     App.vue # 此文件有修改
  5.     router # 此目录下有新增文件
  6.       list.ts # 路由
  7.       index.ts # 有修改
  8.     views # 此目录下有新增文件
  9.       PageA.vue # PageA页面
  10.       PageB.vue # PageB页面
  11.       PageC.vue # PageC页面
  12.   ...... 其他目录及文件暂时不做修改

2.3、修改package.json文件,自动启动浏览器

截止目前为止,咱们通过@vue/cli3脚手架创建的项目在执行npm run serve命令后需要手动打开浏览器,这种用户体验是非常不好的!所以,我们来改进下代码,让其自动启动浏览器。

在vs code或其他编辑器中打开package.json文件,通常情况下应该是第6行。或者直接搜索:"serve": "vue-cli-service serve",然后做如下修改。

  1.   "serve": "vue-cli-service serve", /* 修改前长这样 */
  2.   "serve": "vue-cli-service serve --open", /* 修改后的 */

注意黄色高亮部分,只添加了一个--open属性。现在我们切换到git窗口,输入npm run serve并回车。此时,神奇的一幕就出现了哈!麻麻再也不用担心我要手动复制网址了。

2.4、分离路由文件

为了更好的管理我们的路由,此时我们需要对router/index.ts做些修改,主要是把routes单独放一个文件夹中。

  1. import Vue from 'vue'
  2. import VueRouter, \{ RouteConfig \} from 'vue-router'
  3. import navList from './list' /* 导入路由列表 */
  4. Vue.use(VueRouter)
  5. const routes: Array<RouteConfig> = [] /* 清空原来的 */
  6. routes.push(...navList) /* 把路由添加进来 */
  7. const router = new VueRouter({
  8.   mode: 'history',
  9.   base: process.env.BASE_URL,
  10.   routes
  11. })
  12. export default router

友情提示:上面代码中的\反斜线是为了防止在文章中转码,看官复制后替换为空即可。

注意上面有三处黄色高亮的代码,我们通过import导入了一个文件,然后又清空了原来的routes数组,接着在下方通过pushroutes追加数据。

至于router/list.ts中的内容,看官应该能猜出个一二吧。

  1. import Vue from 'vue'
  2. import \{ RouteConfig \} from 'vue-router'
  3. import Home from '../views/Home.vue'
  4. const navList: Array<RouteConfig> = [
  5.   {
  6.    path: '/',
  7.     name: 'Home',
  8.     component: Home
  9.   },
  10.   {
  11.     path: '/about',
  12.     name: 'About',
  13.     component: () => import(/* webpackChunkName: "About" */ '../views/About.vue')
  14.   },
  15.   {
  16.     path: '/pageA',
  17.     name: 'PageA',
  18.     component: () => import(/* webpackChunkName: "PageA" */ '../views/PageA.vue')
  19.   },
  20.   {
  21.     path: '/pageB',
  22.     name: 'PageB',
  23.     component: () => import(/* webpackChunkName: "PageB" */ '../views/PageB.vue')
  24.   },
  25.   {
  26.     path: '/pageC',
  27.     name: 'PageC',
  28.     component: () => import(/* webpackChunkName: "PageC" */ '../views/PageC.vue')
  29.   }
  30. ]
  31. export default navList

友情提示:上面代码中的\反斜线是为了防止在文章中转码,看官复制后替换为空即可。

至此,现在路由中有5条数据了。

上面的PageA.vuePageB.vuePageC.vue这三个可以通过复制About.vue改名可得,里面没什么内容,简单修改即可,此处就不写了。

2.5、修改App.vue文件

接下来,我们修改App.vue文件,让路由出现在页面上。

  1. /* 代码修改前 start */
  2. <div id="nav">
  3.   <router-link to="/">Home</router-link> |
  4.   <router-link to="/about">About</router-link>
  5. </div>
  6. /* 代码修改前 end */
  7. /* 代码修改后 start */
  8. <div id="nav">
  9.   <router-link to="/">Home</router-link> |
  10.   <router-link to="/about">About</router-link> |
  11.   <router-link to="/pageA">PageA</router-link> |
  12.   <router-link to="/pageB">PageB</router-link> |
  13.   <router-link to="/pageC">PageC</router-link> |
  14. </div>
  15. /* 代码修改后 end */

现在切换到浏览器可以看到页面上显示了5个导航菜单。如图:页面上已经出现了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就完事儿了。

  1. /* 代码修改前 start */
  2. <div id="nav">
  3.   <router-link to="/">Home</router-link> |
  4.   <router-link to="/about">About</router-link> |
  5.   <router-link to="/pageA">PageA</router-link> |
  6.   <router-link to="/pageB">PageB</router-link> |
  7.   <router-link to="/pageC">PageC</router-link> |
  8. </div>
  9. /* 代码修改前 end */
  10. /* 代码修改后 start */
  11. <div id="nav">
  12.   <router-link v-for="(item, index) in $router.options.routes" :key="index" :to="item.path">\{\{item.name\}\} | </router-link>
  13. /* 代码修改后 end */

友情提示:上面代码中的\反斜线是为了防止在文章中转码,看官复制后替换为空即可。

保存后在前台页面上是看不出任何变化的,虽然我们已经优化了代码。[:笑哭]

三、修改页面title

此时我们点击任意导航,浏览器上的title始终没有跟随变化。显然,这对SEO优化而言是非常不利的。

那要怎么搞呢?要是传统的项目,咱们直接找到对应的html页面,修改title标签中的内容即可。但现在是Vue项目,全局只有一个index.html模板文件,硬改肯定是不行的。

3.1、修改router/list.ts文件

由于我们在router/list.ts文件中定义了每个页面的路由信息,所以理应title设置也一起设置。vue官方提供了meta字段,详情请访问→→路由元信息,所以我们可以把title添加进meta中。

  1. ...... /* 原代码未做修改 */
  2. const navList: Array<RouteConfig> = [
  3.   {
  4.    path: '/',
  5.     name: 'Home',
  6.     component: Home,
  7.     meta: {
  8.       title: '首页'
  9.     }
  10.   },
  11.   {
  12.     path: '/about',
  13.     name: 'About',
  14.     component: () => import(/* webpackChunkName: "About" */ '../views/About.vue'),
  15.     meta: {
  16.       title: '关于我们'
  17.     }
  18.   },
  19.   {
  20.     path: '/pageA',
  21.     name: 'PageA',
  22.     component: () => import(/* webpackChunkName: "PageA" */ '../views/PageA.vue'),
  23.     meta: {
  24.       title: '页面A'
  25.     }
  26.   },
  27.   {
  28.     path: '/pageB',
  29.     name: 'PageB',
  30.     component: () => import(/* webpackChunkName: "PageB" */ '../views/PageB.vue'),
  31.     meta: {
  32.       title: '页面B'
  33.     }
  34.   },
  35.   {
  36.     path: '/pageC',
  37.     name: 'PageC',
  38.     component: () => import(/* webpackChunkName: "PageC" */ '../views/PageC.vue'),
  39.     meta: {
  40.       title: '页面C'
  41.     }
  42.   }
  43. ]
  44. export default navList

友情提示:上面代码中的\反斜线是为了防止在文章中转码,看官复制后替换为空即可。

保存代码后刷新页面,你会发现什么变化都没有,跟刚才没修改前一模一样![:笑哭]

懵逼不?不用怀疑代码写错了,因为步骤还没有完!

3.2、“全局前置守卫”登场

之所以页面标题没有跟随路由发生变化是因为我们没有进行手动干预!我们可以通过官方提供的router.beforeEach对要跳转的路由进行拦截并干点儿其他的事情。详情请访问导航守卫

  1. ...... /* 以上代码未做修改 */
  2. const router = new VueRouter({
  3.   ...... /* 此处代码未做修改 */
  4. })
  5. router.beforeEach((to: Route, from: Route, next: NavigationGuardNext<Vue>) => {
  6.   if (to.meta) {
  7.     document.title = to.meta.title || '无标题' /* 动态设置页面标题 */
  8.   }
  9.   next()
  10. })
  11. export default router

现在,我们再点击页面上的导航菜单可以看到浏览器地址栏前的title已经跟随页面发生了变化。
如图:通过全局前置守卫来修改页面的title.gif通过全局前置守卫来修改页面的title

四、demo源码

本篇源码已上传到了github上的dev-recursive-navigation-1-20200719分支中。如果看官需要研究源码,可以点击下面的链接进行访问并下载。

  1. 网址: 戳我前往github查看源码
转载声明:
  若亲想转载本文到其它平台,请务必保留本文出处!
本文链接:http://www.yilingsj.com/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的安全区域

评论区