Vue router-link仅首次点击生效问题排查求助
问题根源及解决方案
你遇到的问题是Vue组件复用导致的生命周期钩子不触发——当你在News.vue里点击不同的路由链接时,Topnews.vue组件并没有被销毁重建,而是被复用了,所以created钩子只会在第一次加载时执行一次,后续路由参数变化时不会重新获取数据。
下面是两种最常用的解决方法:
方法1:监听路由变化(watch $route)
修改Topnews.vue的script部分,添加watch监听$route的变化,每当路由参数更新时重新请求数据:
<template id="topnews1"> <div class="col-sm-7"> <div class="cars"> <img :src="topnews.thumb" class="img-responsive" width=100%/> <div class="name" ><h3>{{ topnews.title }}</h3> <p> <br>{{ topnews.info }}<br/> </p> </div> </div> </div> </template> <script> export default { data:function(){ return {topnews: {title: '', thumb: '', info: ''}} }, created:function() { this.fetchData(); // 把请求逻辑抽成方法,方便复用 }, watch: { '$route': function(to) { this.fetchData(to.params.id); } }, methods: { fetchData(id = this.$route.params.id) { let uri = '/news/' + id; Axios.get(uri).then((response) => { this.topnews = response.data; }); } } } </script>
这里把数据请求逻辑抽成了fetchData方法,既可以在created里初始化调用,也可以在路由变化时调用,保持代码复用性。
方法2:使用路由守卫beforeRouteUpdate
Vue提供了专门的路由守卫beforeRouteUpdate,用于在当前路由改变但组件被复用时触发,你可以用它来更新数据:
<template id="topnews1"> <!-- 模板部分不变 --> </template> <script> export default { data:function(){ return {topnews: {title: '', thumb: '', info: ''}} }, created:function() { this.fetchData(); }, beforeRouteUpdate(to, from, next) { // 获取新的路由参数id,重新请求数据 this.fetchData(to.params.id); next(); // 必须调用next()才能完成导航 }, methods: { fetchData(id = this.$route.params.id) { let uri = '/news/' + id; Axios.get(uri).then((response) => { this.topnews = response.data; }); } } } </script>
这种方法更贴近路由相关的逻辑处理,适合需要在路由切换前做一些操作的场景。
额外方法:强制组件销毁重建(不推荐,除非必要)
如果你不想修改Topnews.vue的代码,也可以在父组件的<router-view>上绑定:key="$route.fullPath",这样每次路由变化时都会销毁重建组件,从而触发created钩子:
<router-view :key="$route.fullPath"></router-view>
不过这种方法会带来组件销毁重建的性能开销,所以优先推荐前两种方法。
为什么原来的代码会出现这种情况?
当Vue-router发现当前组件可以复用时(比如从/news/1到/news/2,都是同一个Topnews组件),它会复用现有组件实例,而不是创建新的。这是Vue的性能优化策略,但也导致created、mounted这类只会执行一次的钩子不会再次触发,所以我们需要手动监听路由变化来更新数据。
内容的提问来源于stack exchange,提问作者mr Enthusiast
相关产品推荐
相关产品推荐

