Vue router前端路由笔记

路由概念

路由这一概念最早出现在后端(即后端渲染),前端是没有的。

它经历了三个阶段的演进:由后端路由(让服务器去处理)到前后端分离的开发模式(也就是Ajax的出现),再到单页面富应用阶段(Simple Page web Application,即SPA)


目前前端流行的三大框架,都有自己的路由实现:
  • Angular的ngRouter
  • React的ReactRouter
  • Vue的vue-router(是官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用)
vue-router是基于路由和组件的
  • 路由用于设定访问路径,将路径和组件映射起来
  • 在vue-router的单页面应用中,页面的路径的改变就是组件的切换
Vue前端路由的核心:
  • 改变URL,但整体页面不再进行刷新,区别于H5的a标签。

而我们常见的大多数网站,当改变URL的时候,都会向服务器发送请求数据,然后再渲染到页面上,这一过程会导致页面重新加载刷新,而使用前端路由实现则不会如此。

Vue实现前端路由的两种方式:
  • URL的hash,即我们通常称哈希模式(#)。
  • H5的history模式:pushState | replaceState | go | back
哈希模式:location.hash="path"
URL中的hash
  • URL中的hash也就是锚点(#),本质上是改变window.location的href属性(hype reference,超链接引用)
  • 通过直接赋值location.hash来改变href,致使页面不会发送刷新
history模式(栈结构)
  • 栈结构就像一个弹夹,最新进栈都会被压在栈底,
  • 原理是先进后出,出栈只能先从栈顶往下,然后拿东西,
  • 队列是先进先出。
history.pushState({}, '', 'paht'),即入栈模式

history.back()返回上一层的页面(类似返回上一次的历史记录,即出栈模式)。
history.replaceState()替换模式

替换模式不是压入栈,此外,返回按钮也不能用。






小结:
  • history.back()等价于 history.go(-1)
  • history.forward()等价于 history.go(1)
  • 这两个接口等同于浏览器界面上的前进后退按钮
安装路由
  • 如果在脚手架创建模板的时候,没有勾选配置路由,现在是可以通过npm进行安装的。

  • 使用Vue CLI2版本配置的路由,出现在src源码目录下。


  • 为了帮助我们更好地加深认知router,直接删除改文件夹,自己手动配置路由。

Vue CLI2脚手架手动配置路由具体步骤如下:
  • 在src源码目录下创建一个名叫router的文件夹,在该文件夹(router)下创建一个index.js的脚本文件,在index.js这个脚本文件里面配置路由相关的信息。


  • index.js文件配置路由相关信息详情:


  • 在main.js入口文件进行导入操作使用。


  • 到这里,路由的框架已经具备搭建好了,现在只差配置路由的映射关系。

为了保持整洁的页面,将脚手架默认创建的组件删掉(即Hello World.vue文件),保持一个空的components目录即可。

清除App.vue的模板内容,保持整洁。



在components目录下创建一个About.vue组件和一个Home.vue组件。



内容如下:
  • 在index.js里面配置路径的映射关系。


  • 一个对象是一个映射关系。



  • 来到根组件App.vue配置路由模板,router-link是vue-router自己注册的组件,他们是全局组件,可以在任何位置使用。


  • 页面url效果,类似h5的a标签,其实最终渲染的也是a标签。



    控制台查看发现是个a标签
  • 路由默认值的设置,给用户第一视角,进来的时候就显示出整个网站的首页。


    纠错:重定向路由这里应该是redirect: 'Home',少了引号。

  • 将默认的哈希hash模式改为history模式,因为hash模式自带#号作为默认,看起来有点别扭。



  • router-view 决定组件渲染的位置,它实现的效果是占位。


  • router-view切换组件效果


router-link属性
  • 属性to :用于跳转指定的路径。
  • 属性tag: 默认渲染成a标签,如果想使用其他标签。通过tag属性绑定h5标签使用。

  • 属性replace: 只允许在页面切换,不能使用浏览器的返回按钮。
    要重新打开8080端口,才能看到实际效果。



    属性replace会自带一个class样式的活跃状态类。




    有了它,我们可以写样式效果。

  • active-class属性:用于修改默认的router-link-active样式,一般在进行高亮导航菜单或者底部的tabbar时,会用到该类。

  • linkActiveClass属性:统一修改样式,只不过,它不再是router-link的属性了,而是属于router对象实例属性了。
    我们来到index.js


路由代码实现跳转方式
  • 有时候,页面的跳转可能需要执行对应的JS代码,这个时候,就可以使用第二种跳转方式了。



    但不能点击自身(首页)超过2次否则会报错,首页和分页轮流切换不会报错。



    使用replace可以解决。

Vue动态路由

  • 上面设置的路由都是静态路由。
  • 在某些情况下,一个页面的path路径可能时不确定的,比如我们进入用户界面时,希望是如下这种路径/user/zhangsan或者是/user/lisi
  • 除了有前面的/user之外,我们通常会见到某些网站后面还跟上了对应的id号。
  • 这种path和component的匹配关系,我们称之为动态路由,它也是路由传递数据的一种方式。

代码试图:

  • 创建一个User.vue组件。



  • 在index.js里面配置组件的映射关系。



  • 在App.vue组件里面实现动态绑定路由。



  • 需求:在User.vue组件获取当前用户界面的信息。




路由懒加载方案

  • 当我们通过npm run build打包构建应用的时候,js包会变得非常巨大,会影响页面的加载进程效果。
  • 为什么会这样?
    因为,我们知道路由中通常会定义了很多不同的页面组件,这个页面最后会被打包放在一个js文件中,但是这么多页面组件被压挤在一个js文件中,必然会造成这个页面非常的庞大。
    如果我们一次性从服务器请求下这个页面,可能需要花费一定的时间,甚至导致用户的浏览器出现了短暂的空白情况,用户体验十分不好。
  • 我们能否避免这种页面短暂空白的情况呢?
    官方给出了解释:使用路由懒加载方案可以实现,如果我们能把不同路由对应的组件分割成不同的代码块进行处理,然后当路由被访问的时候加载对应的组件,这样就变得更加的高效了。
  • 路由懒加载到底做了什么?
    路由懒加载的主要作用就是将对应的组件打包成一个个的js代码块。
    只有在这个路由被访问到的时候,才开始加载对应的组件。


打包js文件的解析

路由懒加载的方式(三种)

早期出现2种,一种使用的是异步解决方案,另一种是AMD写法,了解即可。


  • 方式三:ES6方案,在ES6中,我们可以用更加简洁的写法(箭头函数)来组织Vue异步组件和Webpack的代码分割。


  • 为了使用路由懒加载模式,我们需要在index.js里面进行代码重构。


  • 通过npm run build 打包后。


嵌套路由

  • 嵌套路由是一个非常常见的功能,比如我们想在home(首页)中继续进行细分页面的时候就会应用到了嵌套路由了,我们希望通过home首页访问new页面(即/home/new)或者通过/home/detail访问一些内容。
    一个路径映射一个组件,因此,访问这两个路径也会分别渲染2个组件。


    image.png
  • 路径和对应组件的关系如下:

    实现嵌套路由步骤:
  • 创建对应的子组件,填写简洁模板即可。



  • 在index.js中配置路由映射,并且是配置对应的子路由(这里我们配置的是home首页的子路由),使用到children(子路由)数组可以包含多个对象。

路由懒加载配置



children配置子路由


  • 在组件内部使用占位标签<router-view>,因为我们的新闻页面(news)和详情页(details)是在首页里面配置子路由的,所以我们是在home页里面使用占位标签<router-view>进行显示。





    但当我们点击其他页面,然后再回来点击首页,发现我们点击原来子路由的(新闻页面)时,新闻页面的内容消失了,而我们希望是默认显示新闻页面的。


所以我们需要在子路由下面进行重定向,默认显示news页面。


路由的参数传递,传递参数主要有2种类型:分别是params和query

params的类型

  • 配置路由格式(index.js): /router/:id


  • 传递的方式(App.vue):在path后面跟上对应的值



  • 传递后形成的路径(User.vue):/router/id
  • 从Profile.vue中取App.vue的值。


query的类型

  • 配置路由格式:/router,也就是普通配置路由即可。

创建Profile.vue组件。


index.js文件中,进行路由懒加载配置。



普通路由映射配置。


  • 传递的方式(App.vue中):对象中使用query的key作为传递方式


  • 传递后形成的路径:/router?id=123, /router?id=abc




  • 从Profile.vue中取App.vue的值。



路由代码实现路由参数跳转方式

  • 定义2个按钮,绑定相对应的路由点击事件。



全局导航守卫

全局导航守卫是个啥?

  • vue-router提供的导航守卫主要用来监听路由的进入和离开的。
  • vue-router提供了beforeEach前置守卫(guard)钩子(hook)函数和afterEach的后置导航钩子函数(路由跳转完后实现回调机制),他们会在路由即将改变前和改变后触发。
  • 简单点就是想监听路由来回跳转的过程,获取路由跳转到哪个位置,然后在监听函数里面搞事情。

全局导航守卫实际效果是啥?

  • 就是想实现我们的网页置顶title标签
  • 当我们点击首页的时候,title变成首页,点击用户页面的时候,title变成用户,有点类似小程序和app头顶上的NavigationBar导航,点击了哪个导航,就显示对应的title。

怎么实现上述效果呢?

给每个对应的参与路由跳转的组件添加生命周期钩子函数,created.

我们来看下title的效果:


小结:

  • 我们上面采用的是比较普通的实现方式,我们会想到其实修改标题的位置就是每一个路由对应的.vue组件文件。
    -通过created生命周期函数,执行对应的代码进行修改即可
  • 虽然效果可实现了,但一个个去修改显然有点唐突+狼狈了(几百个页面的时候就显然不合适这样的操作去维护)。

导航守卫的使用

  • 真正的全局守卫导航是在router/index.js里面配置的。
  • 我们首先拿到router对象,这个router对象里面有一个beforeEach()方法,这个beforeEach()方法里面有三个参数,分别是to, from, next


  • 我们可以利用beforeEach来完成对导航标题的修改。
  • 我们可以在钩子当中用meta来定义一些标题。
  • 其次呢,利用导航守卫修改我们的标题。

beforeEach导航钩子三个参数的解释:

  • to: 即将进入的目标路由对象。
  • from: 当前导航即将要离开的路由对象。
  • next: 调用该方法后,才能进入下一个钩子,不调用一下next()方法的话,整个页面的路由跳转将会被拦截,next方法告诉浏览器下一步要干嘛,千万别给我拦截了。
  • 大概就是从from跳转到to

显然我们不能拿到to.title这样一个的数据

  • 所以要在组件映射里面添加每个对应的meta属性(元数据:描述数据的数据)




    这样全局导航守卫效果总体就实现了,但还有一点瑕疵,就是当我们点击首页的时候,title变成了undefine。



    为什么会这样?
    这和我们在首页里面使用了嵌套子路由有关系。
    我们尝试打印to对象看下。

    所以我们只要找到matched(匹配)的0号位,就能解决子路由这块的小bug




如果是后置钩子函数,即afterEach,不需要主动调用next()函数。

  • 上面我们使用的导航守卫,叫做全局守卫
  • 此外还有路由独享的守卫、组件内的守卫。

keep-alive遇上vue-router

keep-alive可以保留组件内部切换回来的显示之前用户的浏览状态。

比如我们当前在首页,点击了新闻详情页面子路由,然后去点击了档案,现在再回去点击首页,发现它停留在了新闻页面,而不是我们想回去刚刚浏览过的新闻详情页面,遇到这种状况的话,就要使用keep-alive去解决了。



那为什么会出现这样的情况呢?
我们用生命周期函数测试下就明白了。




我们可以看到,当我们点击首页的时候,组件被创建生成,点击其他页面的时候,组件已经销毁了,如此一直循环下去,默认显示的都是新闻页面,而不是新闻详情页面。

keep-alive(保持组件活着)概念理解,结合代码解决上面提出的问题。

  • keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
    keep-alive有2个重要属性
  • include - 字符串或正则表达,只有匹配的组件会被缓存。
    -exclude - 字符串或正则表达,任何匹配的组件都不会被缓存。


  • router-view也是一个组件,如果直接被包在keep-alive里面,所以路径匹配到的试图组件都会被缓存。



    我们还要注销掉首页下,默认新闻页面内容展示。


我们需要用到组件内的守卫知识:beforeRouteLeave
官网:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342