想利用暑假时间好好学习一下vue,会记录每一天的学习内容。
今天是学习vue的第12
天!
起起伏伏乃人生常态,继续加油~
1. $router 和 $route
$router
和 $route
是有区别的
$router
为VueRouter
实例,想要导航到不同URL
,则使用$router.push()
方法$route
为当前正处于活跃状态的路由,可以获取里面的name
、path
、query
、params
等
测试一下$router
:
在main.js
中添加控制台输出语句
console.log(router);
这里的router
是我们从配置router
文件夹的index.js
文件中引入的
引入的这个router
实际上就是index.js
中创建的VueRouter
实例
然后随意挑一个组件,在其文件中同样添加打印语句,输出$router
这里我选了Home
组件
是的,$router
是 VueRouter
实例,对比一下各个属性,可以发现是一样的
测试一下$route
:
也是随便挑几个子组件里面写打印语句就好
会发现$route
就是当前正处于活跃状态的路由,里面还有些常用的属性可以让我们取用
2. 路由的导航守卫
我们来考虑一个需求:在一个SPA应用中,如何改变网页的标题?
- 网页标题是通过
<title>
来显示的,但SPA只有一个固定的HTML,切换不同的页面时,标题并不会改变 - 但是我们可以通过JavaScript来修改
<title>
的内容,window.document.title = '新的标题'
- 那么在Vue项目中,在哪里修改?什么时候修改比较合适?
使用导航守卫:
vue-router
提供的导航守卫主要用于监听路由的进入和离开vue-router
提供了beforeEach
和afterEach
的钩子函数,它们会在路由即将改变前和路由改变后触发
导航守卫使用
我们可以利用beforeEach
来完成标题的修改
- 首先,我们可以在路由中定义一些标题,用
meta
属性来定义
- 然后,利用导航守卫,修改我们的标题
to
实际上是我们要进入的下一个路由对象,而我们上面给每个路由对象都定义了meta
属性,我们通过meta.title
就能拿到标题了
导航钩子的三个参数:to
:即将要进入的目标路由对象from
:当前导航即将要离开的路由对象next
:调用该方法后,才能进入下个钩子
⚠️:next()必须要调用!!!
基本都可以正常显示标题了
⚠️除了Home
页,显示了undefined
这其实是因为这个页面里我们用了嵌套路由
,那么怎么解决呢?来打印一下to
参数看看
可以看到meta
属性是空的,在里面找不到title
,这时应该看matched
属性
我们应该要拿的是这个matched
数组,0号下标对象中的这个meta
属性的title
!!
那么应该改为to.matched[0].meta.title
,这里下标一定是0!!因为我们要拿到的永远是第一个来当标题
成功显示:
导航守卫补充
beforeEach()
我们称为前置守卫
afterEach
我们称为后置钩子
补充1:如果是后置钩子,也就是afterEach
,不需要主动调用next()
函数
router.afterEach((to, from) => {
// ...
})
补充2:上面我们使用的导航守卫,被称之为全局守卫,除了全局守卫,也还有别的类型的守卫
- 路由独享的守卫
可以在某个路由对象中直接定义beforeEnter
守卫:
const router = new VueRouter({
routes: [
{
path: '/About',
component: About,
beforeEnter: (to, from, next) => {
// 只有进入到about组件中才会打印这句话
console.log('about beforeEnter');
next();
}
}
]
})
- 组件内的守卫(可在路由组件中直接定义
beforeRouteEnter
:在导航进入该组件的对应路由时调用- 不能获取组件实例
this
,因为当守卫执行前,组件实例还没被创建
- 不能获取组件实例
beforeRouteUpdate
:在当前路由改变,但是该组件被复用时调用- 举例来说,对于一个带有动态参数的路径
/user/:userid
,在/user/id1
和/user/id2
之间跳转的时候,由于会渲染同样的user
组件,因此组件实例会被复用,而这个钩子就会在这个情况下被调用。 - 可以访问组件实例
this
- 举例来说,对于一个带有动态参数的路径
beforeRouteLeave
:导航离开该组件的对应路由时调用- 可以访问组件实例
this
- 可以访问组件实例
3. keep-alive
我们仍有一个待解决的问题:
- 我们每次切换组件,都在不断创建新进入的组件、销毁离开的组件
- 也就是说我们组件内部的状态是没有被保留下来的
下面来验证一下,是不是真的每次都切换都会创建一个新组件,销毁原组件:
我这里拿 About
组件当例子,用生命周期函数来测试:
(不太理解生命周期可以去看我整理过的关于生命周期的一篇文章https://blog.csdn.net/gegegegege12/article/details/118468539.)
可以看到,当我们反复切换页面,不断进进出出About
组件的时候,About
组件是在不断被创建又被不断销毁的
如果我们希望状态能够保留,而不是每次都不断创建有销毁,可以使用keep-alive
keep-alive
是vue内置的一个组件,可以使被包含的组件保留状态,或者避免重新渲染router-view
是vue-router内置的一个组件,如果直接被包在keep-alive
里面,所有路径匹配到的组件都会被缓存
具体实现
非常简单,将App.vue
中的router-view
包裹在keep-alive
里面
<keep-alive>
<router-view></router-view>
</keep-alive>
这时我们再不断进进出出About
组件的时候,只会在第一次进入的时候触发created()
钩子,离开时也不会触发destroyed
钩子,因为并不会销毁组件
keep-alive的属性
它有两个非常重要的属性:
include
:字符串/正则表达式,只有匹配的组件会被缓存exclude
:字符串/正则表达式,任何匹配的组件都不会被缓存
<!-- Home和About组件不会被缓存-->
<!-- 这里要在他们的组件中定义name属性才能用-->
<!-- Home和About之间不能写空格!!!-->
<keep-alive exclude="Home,About">
<router-view></router-view>
</keep-alive>