Vue3中watch監(jiān)聽器及源碼學習
更新時間:2024年01月21日 11:40:24 作者:Unique·Blue
本文主要介紹了Vue3中watch監(jiān)聽器及源碼學習,Watch偵聽器在Vue3中特性進行了一些改變和優(yōu)化,下面來詳解的介紹一下基本使用,具有一定的參考價值,感興趣的可以了解一下
示例均采用 <script setup>,且包含 typescript 的基礎用法
前言
在 vue3 中,必須是 ref、reactive 包裹起來的數(shù)據(jù),才可以被 watch 監(jiān)聽到
一、基本使用
1、語法:watch(source, cb, options)
- source 是監(jiān)聽的目標,有 4 種書寫形式:
reactive形式的響應式數(shù)據(jù)ref形式的響應式數(shù)據(jù)- 數(shù)組形式:監(jiān)聽多個響應式數(shù)據(jù)時(應該用的不多)
- 挨個放進
數(shù)組里,如[響應式數(shù)據(jù)1, 響應式數(shù)據(jù)2] cb對應的函數(shù)參數(shù)(新值、舊值)也都是數(shù)組形式,詳見例子
- 挨個放進
- 函數(shù)形式:若只想監(jiān)聽
reactive 深層中的指定屬性,該指定屬性是引用類型,不需要函數(shù)形式,直接 obj.a.b非引用類型,比如是一個字符串,則需要使用函數(shù)形式返回,詳見例子
- cb 是回調函數(shù),
(newVal,oldVal) => {} - options 是配置項
deep: 是否開啟深層監(jiān)聽reactive類型的數(shù)據(jù)不需要開啟,源碼中已做了深層響應式ref類型的數(shù)據(jù)如果需要監(jiān)聽到深層,要設置為true(雖然監(jiān)聽到深層,但是 source 不能指定到深層)
immediate: 是否立刻執(zhí)行flush: watch 的執(zhí)行順序。pre組件更新之前執(zhí)行(默認)sync同步執(zhí)行;post組件更新之后執(zhí)行
2、例子
下面代碼中,演示了多個情景下的使用
<input type="text" v-model="xiaoman1" /> <br /> <input type="text" v-model="xiaoman2" /> <br /> <input type="text" v-model="message.foo.bar" /> <br /> <input type="text" v-model="message2.foo.bar" />
const xiaoman1 = ref<string>("小滿1");
const xiaoman2 = ref<string>("小滿2");
const message = ref({
foo: {
bar: "aaaaa",
},
});
const message2 = reactive({
foo: {
bar: "aaaaa",
},
});
watch(xiaoman1, (newVal, oldVal) => {
console.log("監(jiān)聽單個數(shù)據(jù)源", newVal, oldVal);
});
// 用數(shù)組監(jiān)聽多個數(shù)據(jù)源,[新值數(shù)組], [舊值數(shù)組]
watch([xiaoman1, xiaoman2], (newVal, oldVal) => {
console.log("用數(shù)組監(jiān)聽多個數(shù)據(jù)源,[新值數(shù)組], [舊值數(shù)組]", newVal, oldVal);
});
// ref 深層監(jiān)聽
watch(
message,
(newVal, oldVal) => {
// 如果是引用類型,新值 和 舊值 是一樣的
console.log("ref 深層監(jiān)聽&立刻執(zhí)行", newVal, oldVal);
},
{
deep: true, // 深度監(jiān)聽,ref 若需要深度監(jiān)聽,這里要開啟
immediate: true, // callback 立刻先執(zhí)行一次
flush: "pre", // 【watch的執(zhí)行順序】 pre 組件更新之前調用(默認);sync 同步執(zhí)行;post 組件更新之后執(zhí)行
// flush 屬性在 watch 中用的不多,watchEffect中可能用到
}
);
// reactive 深層監(jiān)聽:不必開啟深度監(jiān)聽
watch(
message2,
(newVal, oldVal) => {
// 如果是引用類型,新值 和 舊值 是一樣的
console.log("reactive 深層監(jiān)聽&立刻執(zhí)行", newVal, oldVal);
},
{
// deep: true, // reactive 不必開啟深度監(jiān)聽,源碼已做了深層監(jiān)聽
// immediate: true,
}
);
// 若只想監(jiān)聽 reactive 深層中的單個屬性,(第一個參數(shù))引用類型可直接寫,否則使用函數(shù)形式
watch(
message2.foo, // 監(jiān)聽到 foo,foo是引用類型,直接寫就行
// () => message2.foo.bar, // 監(jiān)聽到 bar,需要用函數(shù)形式
(newVal, oldVal) => {
// 如果是引用類型,新值 和 舊值 是一樣的
console.log("reactive 監(jiān)聽深層中的單個屬性", newVal, oldVal);
}
);
二、源碼學習
由于源碼較多,這里不做截圖
/** * * @vue/runtime-core/runtime-core.cjs.prod.js 搜索 function watch * * - watch(source, cb, options) * * - source 有很多種類型,reactive、ref、數(shù)組、函數(shù),所以先判斷類型,格式化source * - ref 類型,直接把 value 取出來,賦值給 getter * - reactive 類型,直接把整體賦值給 getter,deep 手動置為 true 即可(reactive已經(jīng)進行了深度監(jiān)聽) * - 數(shù)組類型,做遍歷,對每一項再判斷類型,分別處理完之后丟進新數(shù)組返回 * - ref類型,返回.value * - reactive類型,遞歸處理后返回 * - 函數(shù)的話,進行加工 * - 函數(shù)類型 * - 判斷有沒有 cb * - 有 cb 的話,同樣也是對函數(shù)做了加工賦值給 getter * - 沒有 cb,走進 watchEffect(下一章) * * - deep處理: * - cb、deep 若同時存在,即 有回調函數(shù) 且設置了 深度監(jiān)聽,進行 traverse 遞歸深度監(jiān)聽(當然是更耗時的) * * - flush處理:先初始化出 scheduler 調度器 * - sync 同步執(zhí)行,scheduler = job * - post 組件更新后,將 job 通過 queuePostRenderEffect 函數(shù)處理后再賦值給 scheduler * - 注意,源碼中看到 queuePostRenderEffect 這個函數(shù),一定表示是在組件更新之后再去執(zhí)行 * - pre 組件更新前,queueJob 處理 job 后賦值給 scheduler * * - ReactiveEffect 收集依賴更新: * - 上面步驟 將 getter、scheduler處理好后作為參數(shù) 給到 ReactiveEffect 函數(shù) * - ReactiveEffect 收集好依賴之后,有更新的話 就會觸發(fā) scheduler,也就是說會執(zhí)行 job * * * - cb 存在 * - immediate 為 true 時,會立即調用一下 job * - 內部會先獲取到新值 newVal * - 如果是第一次執(zhí)行,舊值 oldVal 會置為 undefined * - (執(zhí)行完這里才會更新)然后 把新值賦值給舊值,為下一次使用準備 (所以如果是對象,新舊值是相等的) * - immediate 為 false 時, * - 先給舊值做初始化,如 oldVal = '小滿' * - 依賴如果更新,會觸發(fā) scheduler,執(zhí)行 job * - job 內新值 newVal = '小滿1' * - 舊值 oldVal 不會走進 undefined,會等于原有的 oldVal = '小滿' * - (執(zhí)行完這里才會更新)會把 oldVal = '小滿1' * * */
到此這篇關于Vue3中watch監(jiān)聽器及源碼學習的文章就介紹到這了,更多相關Vue3中watch監(jiān)聽器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue+Element-UI中el-table動態(tài)合并單元格:span-method方法代碼詳解
el-table是element-ui提供的表格組件,可以用于展示和操作數(shù)據(jù),這篇文章主要給大家介紹了關于Vue+Element-UI中el-table動態(tài)合并單元格:span-method方法的相關資料,需要的朋友可以參考下2023-09-09

