Vue3.5新增的baseWatch让watch函数和Vue组件彻底分手

前言

Vue 3.5.0-beta.3版本中新增了一个base watch函数,这个函数用法和我们熟知的watch API一模一样。区别就是我们之前用的watch API是和Vue组件以及生命周期是一起实现的,他们是深度绑定的。而Vue3.5新增的base watch函数是一个新的函数,他的实现和Vue组件以及生命周期没有一毛钱关系。

加入欧阳的高质量vue源码交流群、欧阳平时写文章参考的多本vue源码电子书

@vue/runtime-core

vue3是模块化设计,他将核心功能拆分为多个独立的模块,如下图:
modules

比如reactivity模块中就是响应式的核心代码、runtime-core模块就是运行时相关的核心代码、compiler-core模块就是编译相关的核心代码。

并且这些模块还被单独当作npm包进行发布,命名规则是@vue+模块名。比如reactivity模块对应的npm包就是@vue/reactivity。如下图:
npm

所以如果我们只需要vue的响应式功能,理论上只需要导入@vue/reactivity包即可。比如我之前的文章: 涨见识了!脱离vue项目竟然也可以使用响应式API,在这篇文章中我就介绍了如何脱离Vue项目,在node.js项目中使用vue的响应式API。

但是不知道你有没有注意到,在demo中我是require("vue"),而不是require("@vue/reactivity")

因为watch不是由@vue/reactivity中导出的,而是由@vue/runtime-core中导出的,如果我只引入@vue/reactivity就会报错了。

const { ref, watch, watchEffect } = require("vue");

const count = ref(0);

// 模拟count变量的值修改
setInterval(() => {
  count.value++;
}, 1000);

watch(count, (newVal) => {
  console.log("触发watch", newVal);
});

watchEffect(
  () => {
    console.log("触发watchEffect", count.value);
  },
  {
    flush: "sync",
  }
);

watch的实现是和vue组件以及生命周期深度绑定的,而vue组件以及生命周期明显是和响应式无关的。他们的实现是在runtime-core模块中,而非reactivity模块中,这也就是为什么watch的实现是放在runtime-core模块中。
runtime

据说性能是 Taro 10 倍的小程序框架 vuemini 底层也是依靠@vue/reactivity实现的,但是由于watch是由@vue/runtime-core中提供的,小程序框架却只引入了@vue/reactivity,所以作者不得不手写了一个watch函数。
vue-mini

重构watch函数

智子在写Vue Vapor时又拆了一个新的模块,叫做runtime-vapor。如果你不了解Vue Vapor,可以看看我之前的文章: 没有虚拟DOM版本的vue(Vue Vapor)
vue-vapor

他们遇到一个问题需要在runtime-vapor模块中使用watch函数,而watch函数是位于runtime-core模块中。但是又不应该在runtime-vapor模块中直接引用runtime-core模块,所以Vue Vapor团队的绚香音就将watch函数重构到了reactivity模块中,这样在runtime-vapor模块中直接使用reactivity模块中的watch函数就行了。

这也就是为什么需要重构watch函数到reactivity模块中。

在欧阳的个人看法中watch函数本来就是属于响应式中的一部分,他在runtime-core模块中反而不合理。在欧阳第一次看vue3源码时就在奇怪为什么没有在reactivity模块中找到watch函数的实现,而是在runtime-core模块中实现的。

当watch函数重构到reactivity模块后,小程序框架 vuemini 的作者也发了一篇帖子。
X

watch函数重构到reactivity模块后,小程序框架中手写的watch函数都不需要了,因为reactivity模块已经提供了。

看见完了!这下 Vue Mini 真成 @vue/reactivity 套壳了...这个评论后,对不起!杨明山大佬欧阳确实没忍住笑出了声。

总结

vue3.5版本中,Vue Vapor团队在reactivity模块中重构实现了一个watch函数。重构的这个watch函数和我们现在使用的watch函数用法是一样的,区别在于以前的watch函数的实现和Vue组件以及生命周期是深度绑定的,而重构的watch函数和Vue组件以及生命周期一毛钱关系都没有。

这个改动对于普通开发者可能没什么影响,但是对于下游项目,比如Vue mini来说还是很受益的。因为以前他们需要自己去手写watch函数,现在reactivity提供了后就不需要这些手写的watch函数了。

最后推荐一下欧阳自己写的开源电子书vue3编译原理揭秘,看完这本书可以让你对vue编译的认知有质的提升,并且这本书初、中级前端能看懂。完全免费,只求一个star。

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3中,可以使用`watch`函数来监听父组件传给子组件的值。根据引用[1]中的代码,子组件通过`defineExpose`暴露了自己的属性`inputVal`和方法`exposeFun`。在父组件中,可以使用`watch`函数来监听子组件的属性变化。例如,如果要监听子组件的`inputVal`属性,可以这样写: ```javascript import { watch } from 'vue'; watch(() => SonVue.inputVal, (newVal, oldVal) => { console.log('子组件的inputVal发生变化', newVal, oldVal); }); ``` 这样,当子组件的`inputVal`属性发生变化时,回调函数就会被触发,并打印出新值和旧值。需要注意的是,`watch`函数的第一个参数是一个函数,返回要监听的值,而不是直接传入要监听的值本身。所以在这里,我们使用了箭头函数来返回`SonVue.inputVal`。 另外,根据引用[3]中的代码,`watch`函数还可以监听多个值或对象的属性。如果要监听多个值,可以将这些值放在一个数组中传入`watch`函数。如果要监听对象的属性,可以将一个函数返回这个属性的值。例如,如果要监听子组件的`inputVal`和父组件的`msg`,可以这样写: ```javascript watch([() => SonVue.inputVal, () => msg.value], ([newInputVal, newMsg], [oldInputVal, oldMsg]) => { console.log('子组件的inputVal和父组件的msg任意一个发生变化都触发', newInputVal, oldInputVal, newMsg, oldMsg); }); ``` 这样,当子组件的`inputVal`或父组件的`msg`发生变化时,回调函数就会被触发,并打印出新值和旧值。 总结起来,Vue3中可以使用`watch`函数来监听父组件传给子组件的值,可以监听单个值、多个值或对象的属性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值