【发布时间】: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 ago、31 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