-
Notifications
You must be signed in to change notification settings - Fork 2
Description
悲伤的故事是这样开始的
某天早上兴高采烈的来到办公室,打开电脑,准备开始今天计划的coding,感觉项目每天计划的很完美,一切尽在掌握。
于是我打开IDE在前一天的基础上新写了一个模块,这个模块是一个动态的导航列表,就像用户列表那样,显示在页面的左侧,点击不同的用户,右边容器要展示不同的用户信息,这看上去是so easy。
于是我chuachuachua就写了如下的一段代码:
router.js
//路由中模块路由的配置
{path: 'user/:userId', component: User},
user.vue
//user组件代码中初始化的代码
……
beforeMount(){
this.initPage();
},
……
methods: {
initPage(otherParams = {}){
otherParams = {
userId:String(this.$route.params.userId),
……
};
this.getDataList(otherParams);
}
}
nav.vue
//导航页面中模块的代码
<el-submenu index="2" class="menu-border-bottom">
<template slot="title"><i class="el-icon-key"></i>用户列表</template>
<el-menu-item :index="`/index/user/${item.id}`" :key="item.id"
v-for="(item, i) in userList"
>
<span>·</span>{{item.userName}}
</el-menu-item>
</el-submenu>
好了,compile一下,愉快的打开浏览器,查看效果,点一个导航,url路由地址变成了user/1
,完美,一切尽在掌握之中,再点另外一个,url路由地址变成了user/2
,哎哎哎,右侧内容怎么没变呢,于是又点了其他几个用户,路由变了,右侧内容还是第一个的并没有变。
一脸懵逼了……
理智分析
懵逼是解决不了问题的,于是开始分析,为什么路由变了,右侧内容没变呢?不应该是点一下导航,重新加载一次组件吗?重新加载组件,不应该是组件的生命周期从新再来一遍吗?
于是带着这些疑问,开始断点加日志的调试,首先是在组件中监视(watch
)获取路由中的参数并打印出来,然后点击之后看效果是能获取到每个不同路由的参数的,于是说明是路由的变化组件是能监视到的。
然后我又在生命周期的beforeMount
内打印日志,点击观测结果,结果果然是在我预想范围之内的:只要在第一次点击的时候,组件的beforeMount
才会被打印,之后再点击就不会打印了。
于是,可以得出结论:当使用路由参数时,原来的组件实例会被复用,并且不会调用重新执行完整的生命周期钩子。
重燃希望
知道是哪里出了问题,就按照这个思路开始fix,既然复用的时候不会重新执行组件的生命周期,而路由变化的时候watch
是有效的,那就在watch
中监视路由的变化,并触发在beforeMount
时做的事情,应该就能解决这个问题了。
于是,在user.vue中加入了如下代码:
watch:{
$route(newVal, oldVal){
if(newVal.params.userId!=oldVal.params.userId){
this.initPage();
}
}
}
带着期待的心情compile了一下,赶紧去试了一下,可以了。哦也,搞定~
总结
当使用路由参数,渲染同一个组件的时候,组件在路由变化的时候不会反复的初始化,而是会被复用,这也就导致组件的生命周期钩子不会再被调用(第一次之后的调用都会没有效果)。
其实,在vue-router的文档中也有详细的讲解到这部分内容,如下:
当使用路由参数时,例如从
/user/1
导航到user/2
,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
其实,这个也不是疑难的大问题,就是新手入门对于实践应用不熟练,对于文档不清楚的问题。
前段时间,在一个前端的微信群里,居然有人在群里问这个问题,所以感觉对于新手来说关于这一点的整理总结还是有必要的,于是就简单的整理了一下。
所以,学习一项新技术,看官方的文档是最好的学习方式,看完官方文档加上适当的编码实践,就会很快很好的掌握一门新技术。
最后这一点也算是这个小坑的一点感悟吧。
每天进步一点点系列
第001篇