三者都是侦听工具,实现的是观察者模式,横向对比
(1)依赖:指的是响应性依赖,也就是侦听 ref、reactive 这类具有响应性的对象。
(2)watch:默认情况下,被侦听对象变化时才会执行,但是可以通过 options 参数设置为可以立即执行
computed
computed 这个单词比较有误导性,看表面是计算用的,但是除了计算之外还可以有其他的功能,比如做个判断、做个序列化、赋值等。
但这些都不是重点,重点是,它和 watch 一样,是侦听用的。
自动侦听 getter 里有响应性的对象,当发生变化时重新执行一次 get 函数,将返回结果存入 _value 缓存,并且通知 template 刷新页面。
所以说,计不计算的不是重点,侦听才是重点。
基础示例
举个例子,我想在网页里看看对象的序列化,用 computed 的实现方式
定义一个 reactive 和 一个 computed,使用 JSON.stringify 实现序列化。
自动收集依赖,侦听 model 的变化,序列化之后交给 template 的 el-input。这样我们就可以在网页里面实时看到对象的序列化情况了。
结构和本质
我们打印一下 computed ,看看结构:
看起来挺复杂的,其实简化一下就简单了,主体是一个 class,其中有若干“私有成员”,然后用访问器实现我们常用的 value 属性,即:
主要结构是这样,当然还需要很多细节才能实现 computed 的功能,如果对细节感兴趣的话,可以看看 Vue 的源码。
计算属性缓存
其实看看源码就好理解了,执行 get 方法时,会把返回值存入 _value ,template 直接从 _value 属性获取数据,在需要更新缓存的时候才会调用 getter,这样就实现了缓存功能。也就是说,使用 _value 属性缓存了执行结果。
可以赋值的方式
computed 也可以开启赋值模式,方法就是传入一个对象,拥有 get 和 set 的对象,可以用在 props 在模板上的绑定。props 的属性是只读的,不能用于 template 的 v-model,那么怎么办?我们可以使用 computed 的赋值模式作为中转站:
子组件:
在子组件里面定义 props 和 emit,然后可以用computed实现“中转”功能,get 里面获取 props 的属性值,set 里面使用 emit 提交更改申请。当然,现在 Vue3.3+ 推出了语法糖 defineModel,就不需要我们自己折腾了。
watch
composition API 的 watch 非常好理解,他是一个函数,第一个参数要指定一个被侦听对象,第二个参数是回调函数,在被侦听的对象发生变化时,执行回调函数。
基础示例
还是上面那个例子,我们看看用 watch 如何实现:(watch 并不适合实现这样的需求,这里仅做对比)
我们先定义一个 ref,然后用 watch 侦听 model,发生变化的时候再做序列化的操作,给 ref 赋值。
对比一下就会发现,对于这种简单的需求,使用 watch 明显没有使用 computed 方便。
不过 watch 可以明确指定侦听的对象,这样对于复杂的情况就不容易乱,不用担心自动收集依赖,把不想被侦听的对象也给收集进来。
watchEffect
一开始没弄明白 watchEffect,后来把三者放在一起一对比就好懂了。
和 computed 对比,相当于没有返回值的 computed,当然也不能 set。
和 watch 对比,可以自动收集依赖,无需手动指定。
这样想就清晰了,排列组合的结果。
是否自动收集依赖、是否有返回值组合一下,
自动收集依赖、无返回:watchEffect
自动收集依赖、有返回:computed需要指定依赖、无返回:watch
基础示例
还是上面那个例子:
不需要自定侦听对象,而是像computed那样可以自动收集,然后还是当model变化时执行序列化的操作,赋值给 ref。
技术前沿拓展
前端开发,你的认知不能仅局限于技术内,需要发散思维了解技术圈的前沿知识。细心的人会发现,开发内部工具的过程中,大量的页面、场景、组件等在不断重复,这种重复造轮子的工作,浪费工程师的大量时间。
介绍一款程序员都应该知道的软件JNPF快速开发平台,很多人都尝试用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。
这是一个基于 Java Boot/.Net Core 构建的简单、跨平台快速开发框架。前后端封装了上千个常用类,方便扩展;集成了代码生成器,支持前后端业务代码生成,实现快速开发,提升工作效率;框架集成了表单、报表、图表、大屏等各种常用的 Demo 方便直接使用;后端框架支持 Vue2、Vue3。如果你有闲暇时间,可以做个知识拓展。
看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~