Skip to content

咦?为什么我设置的vue-router动态路由变了页面不变呢?[每天进步一点点系列] #29

@stuxt

Description

@stuxt

悲伤的故事是这样开始的

某天早上兴高采烈的来到办公室,打开电脑,准备开始今天计划的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>&middot;</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篇

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions