Vue 监听器和计算属性到底有什么不同?

  • Vue 监听器和计算属性到底有什么不同?已关闭评论
  • 183 次浏览
  • A+
所属分类:Web前端
摘要

计算属性和监听器之间的区别是,计算属性有“临时快照”机制,而监听器没有。监听器能做的事情,计算属性也可以做。所以,这一节标题取的就是“难以区别”,但是深入理解的话还是能看出不一样的,也就决定了它们之间的适用场景。


难以区别

计算属性和监听器之间的区别是,计算属性有“临时快照”机制,而监听器没有。监听器能做的事情,计算属性也可以做。所以,这一节标题取的就是“难以区别”,但是深入理解的话还是能看出不一样的,也就决定了它们之间的适用场景。

以下都是个人观点。计算属性的作用就是计算然后返回值,简化模板取值等;监听器更多的意义是监测一个响应式数据的变化从而改变其他的状态。也可以这样理解,计算属性就好像是普通工人在工作,并生产东西;监听器更像是领导在指挥工人怎么做,或如何做。

在讨论计算属性和监听器的区别之前,如果你对计算属性有明确的认知,下文理解起来应该不困难,否则建议你阅读我写的前置文章——《Vue 计算属性与普通的函数有什么区别?》

计算属性

废话不多说,直接上代码。计算某总价:

let price = ref(1); let num = ref(1);  const total = computed(() => {   return price.value * num.value; }); 
<div class="demo2">   Total: {{ total }}   <div>     <span>Price: </span>     <input v-model="price" />   </div>   <div>     <span>Num: </span>     <input v-model="num" />   </div> </div> 

计算属性计算两个响应式数据price以及num,当其中一个数据发生变化时,整个计算属性都将重新执行一次。

我说的是否正确?一验便知:

Vue 监听器和计算属性到底有什么不同?

监听器

监听某商品数量是否发生变化:

let price = ref(1); let num = ref(1); let total = ref(0);  watch(num, (newVal, oldVal) => {   total.value = price.value + newVal; }); 

监听器只监听响应式数据num,如果发生变化就重新计算并赋值给 result。但是,响应式数据price发生变化,就不能够让这个监听器重新计算。可以说,监听器只对num负责,而不受其他响应式数据影响。

我说的是否正确?一验便知:

Vue 监听器和计算属性到底有什么不同?

在输入价格的时候,监听器没有发生任何变化,而当只有数量发生变化的时候,才有了总价。

本节小结

通过上面的代码可以发现,监听器是监测响应式数据num是否发生变化才执行后续的操作,监听器非常具体和精准地知道哪一个被修改了。但是在计算属性里面你能够知道吗?很明显不可以,虽然说有一个数据被修改了计算属性也知道,但是不知道具体的,所以,在计算属性里就不能精准地捕捉,并准对于这一情况做后续的操作。

各自的适用场景

它们之间还有一个区别涉及到性能和开销,计算属性不适用于更改间隔时间短的响应式数据计算,而监听器更加适用。

计算属性

官方文档对于计算属性提到了一个重要的点子——“临时快照”(计算属性的缓存),每当源状态发生变化时,就会创建一个新的快照。

有时候创建快照是没有意义的,对于间隔时间很短的源数据修改,比如输入框输入时页面上的一些变化。输入第一个字符到第二个字符之间的间隔时间,字符有长有短,每一次都要创建“临时快照”,这样是没有意义的,反而可能增加开销。

计算属性除了可以用于复杂的模板取值(普通函数也可以做),还可以计算一次而在页面上多次使用。

监听器

因此,上面说到的情况就更加适合用监听器来做,监听器不创建“临时快照”。监听器更适用于官方文档说的场景:“我们需要在状态变化时执行一些‘副作用’:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态”。

总结

(1)计算属性适合数据源发生变化间隔长,且页面使用它的次数多的情况(区别于普通函数);监听器适合数据源发生变化间隔短,或有异步操作,或有副作用的情况。

(2)如果想要知道具体哪个响应式数据被修改,然后做后续的操作,就使用监听器;不关心哪一个,只要是数据被改动,就都重新执行,就使用计算属性。