写点什么

涨见识了!脱离 vue 项目竟然也可以使用响应式 API

  • 2024-07-30
    福建
  • 本文字数:1804 字

    阅读完需:约 6 分钟

前言


vue3 的响应式 API 大家应该都特别熟悉,比如refwatchwatchEffect等。平时大家都是在vue-cli或者vite创建的 vue 项目里面使用的这些响应式 API,今天欧阳给大家带来一些不一样的。脱离 vue 项目,在node.js项目中使用 vue 的响应式 API


直接上代码


话不多说,直接上代码。这个是我在本地新建的一个最简单的node.js项目,如下图:



从上图可以看到我们的node.js项目依赖只有一个:vue。并且提供了一个名为 dev 的脚本命令,这个脚本命令实际是在 node 环境内执行index.js文件。


我们来看index.js文件,代码如下:

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", });
复制代码


为了标明index.js文件是在node.js环境中运行的,所以这里我特地使用require去导入 vue 导出的refwatchwatchEffect这三个响应式 API。


并且我们还模拟了修改count响应式变量值的操作,使用setInterval每隔一秒让count的值+1

在 vue 项目中一样使用watchwatchEffect去监听count变量的值。


在终端执行yarn dev,也就是执行node index.js,如下图:



从上图中可以看到在node.js中的执行结果和预期是一模一样的。


为什么可以这样写呢?


前面的那个例子是一个node.js项目,项目中我们并没有像 vue 项目那样去创建一个 vue 组件,然后在组件里面去使用响应式 API。而是直接在一个普通的node.js文件中使用 vue 暴露出来的响应式 API,并且watchwatchEffect在监听的值改变后同样触发了对应的 watch 回调,那么这个又是怎么做到的呢?


这得益于 vue3 优秀的模块化设计,他将核心功能拆分为多个独立的模块,如下图:



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

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



得益于模块化的设计,响应式相关的 API 和 vue 组件并没有强关联的关系,所以我们可以在node.js应用中去直接使用响应式 API。


这里使用到了三个响应式 API,分别是:refwatchwatchEffect。在 vue 组件中的响应式的实现原理大家多多少少都有所听闻,其实在node.js项目中实现原理也是一样的,接下来我们讲讲是如何实现响应式的。


在我们这个 demo 中count是一个 ref 的响应式变量,当我们对count变量进行读操作时会触发get拦截。当我们对count变量进行写操作时会触发set拦截。


在我们这里使用watchwatchEffect的代码是下面这样的:

watch(count, (newVal) => {  console.log("触发watch", newVal);});
watchEffect( () => { console.log("触发watchEffect", count.value); }, { flush: "sync", });
复制代码


当代码首次执行到watchwatchEffect时都会对count变量进行读操作,并且watchwatchEffect都传入了一个回调函数。


由于对count变量进行读操作了,所以就会触发get拦截。在get拦截中会将当前 watch 的回调函数作为依赖收集到count变量中。收集的方式也很简单,因为count变量是一个对象,所以使用对象的dep属性进行依赖收集。因为dep属性是一个集合,所以可以收集多个依赖。


在我们这里watchwatchEffect都触发了count变量的 get 拦截,所以watchwatchEffect的回调函数都被count变量进行了依赖收集。


当修改count变量的值时会触发set拦截,在set拦截中做的事情也很简单。将count变量收集到的依赖全部取出来,然后执行一遍。这里收集的依赖是watchwatchEffect的回调函数,所以当count变量的值改变时会导致watchwatchEffect的回调函数重新执行。


这个是整个流程图:



从流程图可以看到响应式的实现原来完全不依赖 vue 组件,所以我们可以在node.js项目中使用 vue 的响应式 API,这也是 vue 的设计奇妙之处。


总结


这篇文章讲了我们可以脱离 vue 项目,直接在node.js项目中使用 vue 的响应式 API。接着讲了响应式的实现原理其实就是依靠get拦截进行依赖收集,set拦截进行依赖触发。


搞清楚响应式原理后,我们发现响应式完全不依赖 vue 组件,所以我们可以在node.js项目中使用 vue 的响应式 API,这也是 vue 的设计奇妙之处。


文章转载自:前端欧阳

原文链接:https://www.cnblogs.com/heavenYJJ/p/18321516

体验地址:http://www.jnpfsoft.com/?from=infoq

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
涨见识了!脱离vue项目竟然也可以使用响应式API_JavaScript_快乐非自愿限量之名_InfoQ写作社区