【问题标题】:Vue update computed property only when outcome changesVue 仅在结果发生变化时更新计算属性
【发布时间】:2023-02-06 11:31:00
【问题描述】:

考虑以下对我遇到的问题的简化:

export default {
    data () {
        return {
            i_change_alot: 0,
        };
    },
    mounted() {
        setInterval(() => {
            this.i_change_alot = Math.random();
        }, 10);
    },
    computed: {
        someComputedValue() {
            this.i_change_alot;
            
            return 'a';
        }
    }
}

我创建了一个属性i_change_alot,它每 10 毫秒更改为一个随机值。这意味着该属性变得非常活跃,因此它将触发计算属性。

通过简单地调用 this.i_change_alot 我触发了一个依赖项(为了示例的目的),但是结果计算属性永远不会改变。

最终结果是计算属性 someComputedValue 每 10 毫秒更新一次,据我所知,这会触发视图重新渲染。

我怎样才能使 someComputedValue 仅在价值/结果变化?

(最初的问题是关于显示反应性相对日期,例如“1 秒前”、“2 秒前”等。但是,一段时间后,这变成了30 minutes ago31 minutes ago,这意味着整整一分钟的字符串表示没有改变,但由于依赖日期属性,它仍然每 10 毫秒重新渲染一次)。

根据https://github.com/vuejs/vue/issues/11399,我可以创建一个带有观察者的结构,但它看起来很违反直觉。

【问题讨论】:

  • 所以,我猜这个不变的代码,return 'a'; 并不是你正在发生的事情的真实表现,有时这个计算属性返回的值变化,尽管不一定是在快速变化的值发生变化时。事实上什么更改计算的输出以更改?是的,为什么不在那个值上放置一个观察者呢?
  • 实际的计算函数执行 return this.$filters.toRelative(this.some_timestamp, this.now);,其中 this.now 是一个日期对象,我使用简单的 setInterval 每秒更新一次。 toRelative 函数在两个日期之间创建一个字符串表示。观察者确实有效,但我在 1 个组件中有 4 次,这意味着我需要 4 个计算属性、4 个观察者和观察者更改的 4 个附加属性,以便我可以在我的视图中使用该附加属性。
  • 如果你想避免不必要的渲染,我建议引入另一个计算属性valueToRender返回someComputedProperty并在模板中使用这个valueToRender。这样,只有当valueToRender发生变化时(即someComputedProperty的输出发生变化),模板才会被渲染。但观察者实际上也是实现这种行为的好工具......
  • 双计算属性构造不起作用,第二个计算属性(指的是第一个)仍然考虑第一个的反应链,导致两者更新相同数量的方式
  • “它看起来很违反直觉”——没关系,因为这样可以很好地控制触发观察者的值。这里的要点是 Vue 反应性不会将 i_change_alot 的值与旧值进行比较,它只是由它被重新分配这一事实触发,与其他反应性值一样。解决方案是使用观察者

标签: vue.js vuejs3 vue-reactivity


【解决方案1】:

为什么 Vue 会在值不变的情况下触发 computed?

因为 Vue 在重新计算之前永远不会知道最终结果是否改变。因此,每次依赖项发生变化时,计算变量都会重新计算,无法避免。

常见的误解是 Vue 通过它们的值来缓存计算变量,但实际上,Vue 通过依赖项的状态来缓存计算变量。

避免过于频繁地重新渲染

您可以创建观察者(如您所知)或将使用计算值的模板包装到组件中。

为什么在这里包装到另一个组件帮助?

因为 Vue 会将您的模板转换为渲染函数。每次依赖项发生变化时,都会重新计算此函数。听起来有点熟?是的,它就像一个计算变量。渲染函数的依赖项是您在模板中使用的所有变量。因此,如果您将频繁更改的变量包装到一个组件中,Vue 将只重新渲染该组件,而避免重新渲染您的大组件。会对你的表现产生很大的影响

【讨论】:

    猜你喜欢
    • 2019-10-03
    • 1970-01-01
    • 2019-10-19
    • 2021-03-20
    • 2019-06-21
    • 2018-05-22
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    相关资源
    最近更新 更多