前言
目前使用vue也有一段时间了,埋头开发的时候也积累了不少困惑,当然,也积累了一些宝贵的经验。平日在论坛和一些评论区中闲逛时,也对很多大佬提出的问题,建议有了点自己的思考。于是便想着手开始动笔,认真的写些有用的东西。
PS:如果没了解过或是忘了computed和watch的基本使用的话,建议还是去翻翻官方文档吧!
https://cn.vuejs.org/v2/guide/computed.html
一、聊聊computed和watch
初学时沉浸在Vue的其他特性当中"无法自拔",没有认真的去琢磨这两个属性。直到上了项目···开始傻傻分不清了才慌忙去翻文档。现在想着在blog中好好总结一下,希望有缘人能看到并且能对你有点帮助吧:)
1、computed
首先为什么会有computed?它解决了什么?
作为本科四年都在开发adr的同学,见惯了View和Class(业务逻辑)的“强分离”,初见模板内表达式直呼真香的同时也带着一丝困惑,既然将view层单独抽出,但又提供了一些可以写逻辑代码的空间,那么不可避免的会有人在模板中塞下如下代码
<div id="example">
{{ example.getMax() > 0 ? 1 : 2}}
</div>
当然,这个例子浅显易懂,但真实的项目中或许有更加复杂的业务逻辑被强塞其中,想象一下,若是复杂的DOM树中夹杂着大量如此复杂的,和业务逻辑相关的表达式,那模板将失去它的简洁明了的特点,并且会让简单的DOM树变得晦涩难懂且难以维护。
由此,computed便来了,它的目标便是–解决和维护可能出现在模板中的一些逻辑表达式。在Vue3中,一些逻辑可以写成如下代码
setup() {
const test = computed(() => example.value.getMax())
// ...也可以做更多的逻辑处理
return {
test
}
}
当模板中较为复杂的逻辑都抽离开来,这样就会使得我们的代码变得更加易懂和可维护了!
computed的响应式
当然,被computed包裹后返回出来的变量是响应式的,比如:
const playlist = computed(() => store.state.playList)
console.log(playlist)
// log:
//ComputedRefImpl {_dirty: true, __v_isRef: true, __v_isReadonly: true, _setter: ƒ, effect: ƒ}
注意这个ComputedRefImpl,有时候你的数据“莫名其妙”失去响应式,而你还不明真相,这是查看一下是否是XXRefImpl,从而判断是否失响。
于是,computed在模板中的作用和普通function作用差异体现出来了普通函数在模板中使用,每次渲染模板都会调用,而computed,Vue内部做了响应式缓存,只有依赖的变量发生变化,才会再执行
2、watch
尤大在官网中建议,滥用watch来代替computed是不可取的,当然,个人认为,watch使用于重量级的业务场景,提供的oldVal和newVal的使用便可看出来,watch也更针对新老数据变更的这种场景。
简单的watch使用就不在这赘述啦,这里我还想再补充一个watch使用知识点----当想监听的数据不是响应式的该如何去做?
很简单,监听一个返回该数据的方法便可
watch(() => props.data, async () => {
todoData()
calculate()
})
注意,props在setup中带来的变量会失去响应式,由此,我们可以传递一个函数进去来解决。
二、自己在日常开发中的使用
1、比如从store中拿取数据,返回到模板中,我便会使用computed,当然传递的函数中间也可以加一些逻辑处理…
const list = computed(() => store.state.XXList)
2、watch一般用于重量级业务场景,比如复杂的计算或者数据处理,还加载着存取数据
const useXXXEffect = (store, XXXRef, progress) => {
const xx = computed(() => store.state.xx)
watch(xx, async (newxx) => {
if (newxx) {
await nextTick()
XXXRef.value.setOffset(progress.value)
}
})
return {
xx
}
}
写在最后
这是一篇偏个人笔记向的文章,笔者功力较浅,希望简单的一些笔记能够对帮助到有需要的人