【问题标题】:Vue Router and VueJS reactivityVue 路由器和 VueJS 反应性
【发布时间】:2026-01-24 09:30:01
【问题描述】:

我的vue-router 有此代码:

{ 
   path: '/templates/:id/items/:itemId', component: Item,
   name: 'item'
},

在项目对象上,我有一个计算属性templateId

templateId() {
   return parseInt(this.$route.params.id, 10);
},

我遇到的问题是,每次我向 url 添加一个锚点(点击一个链接,在 item 组件内),即使组件没有改变,这个属性也会再次计算。

这意味着所有依赖于templateId的计算属性都将被重新计算。

但是 templateId 的值根本没有改变。

这是一个非常简单的 jsfiddle 来解释这个问题:

https://jsfiddle.net/1Lgfn9qh/1/

如果我删除 watch 属性(从不调用),控制台中将不再记录任何内容。

你能解释一下这里发生了什么吗? 为什么即使没有更新任何值,也要重新计算计算的属性? 我怎样才能避免这种情况?

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-router


    【解决方案1】:

    导致这种行为的原因是 route 对象在 Vue 中是不可变的。任何成功的导航都会产生一个全新的路由对象,因此会触发所有计算和观察属性的重新计算。有关详细信息,请参阅https://router.vuejs.org/api/#the-route-object

    要解决这个问题,您可以watch 路由对象并在那里为您过滤相关和不相关的更改

    watch: {
      '$route' (to, from) {
        if(to.path != from.path) { // <- you may need to change this according to your needs!
          this.relevantRoute = to
        }
      }
    }
    

    然后在计算和/或监视的属性中引用手动设置的变量

    templateId() {
      return parseInt(this.relevantRoute.params.id, 10);
    },
    

    【讨论】:

    • 有道理,我明白为什么要重新计算templateId。但是为什么hugeTransaction 没有更新,又要计算templateId 呢?
    • 在 JS 中,对象相等与相同(developer.mozilla.org/en-US/docs/Web/JavaScript/…)之间存在差异。在您看来,templateId 可能没有改变(因为它仍然具有相同的“内容”),但实际上它已经改变了。它现在是一个不同的对象,因此它会触发 Vue 的更改检测。