Skip to content

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

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篇

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions