漲見識了!脫離vue專案竟然也可以使用響應式API

前端欧阳發表於2024-07-25

前言

vue3的響應式API大家應該都特別熟悉,比如refwatchwatchEffect等。平時大家都是在vue-cli或者vite建立的vue專案裡面使用的這些響應式API,今天歐陽給大家帶來一些不一樣的。脫離vue專案,在node.js專案中使用vue的響應式API

關注公眾號:【前端歐陽】,給自己一個進階vue的機會

直接上程式碼

話不多說,直接上程式碼。這個是我在本地新建的一個最簡單的node.js專案,如下圖:
node

從上圖可以看到我們的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,如下圖:
run

從上圖中可以看到在node.js中的執行結果和預期是一模一樣的。

為什麼可以這樣寫呢?

前面的那個例子是一個node.js專案,專案中我們並沒有像vue專案那樣去建立一個vue元件,然後在元件裡面去使用響應式API。而是直接在一個普通的node.js檔案中使用vue暴露出來的響應式API,並且watchwatchEffect在監聽的值改變後同樣觸發了對應的watch回撥,那麼這個又是怎麼做到的呢?

這得益於vue3優秀的模組化設計,他將核心功能拆分為多個獨立的模組,如下圖:
packages

比如reactivity模組中就是響應式的核心程式碼、compiler-core模組就是編譯相關的核心程式碼。

並且這些模組還被單獨當作npm包進行釋出,命名規則是@vue+模組名。比如reactivity模組對應的npm包就是@vue/reactivity。如下圖:
npm

得益於模組化的設計,響應式相關的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的回撥函式重新執行。

這個是整個流程圖:
progress

從流程圖可以看到響應式的實現原來完全不依賴vue元件,所以我們可以在node.js專案中使用vue的響應式API,這也是vue的設計奇妙之處。

總結

這篇文章講了我們可以脫離vue專案,直接在node.js專案中使用vue的響應式API。接著講了響應式的實現原理其實就是依靠get攔截進行依賴收集,set攔截進行依賴觸發。

搞清楚響應式原理後,我們發現響應式完全不依賴vue元件,所以我們可以在node.js專案中使用vue的響應式API,這也是vue的設計奇妙之處。

關注公眾號:【前端歐陽】,給自己一個進階vue的機會

相關文章