国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【源碼系列#04】Vue3偵聽器原理(Watch)

這篇具有很好參考價值的文章主要介紹了【源碼系列#04】Vue3偵聽器原理(Watch)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

專欄分享:vue2源碼專欄,vue3源碼專欄,vue router源碼專欄,玩具項目專欄,硬核??推薦??
歡迎各位ITer關注點贊收藏??????

語法

偵聽一個或多個響應式數(shù)據(jù)源,并在數(shù)據(jù)源變化時調(diào)用所給的回調(diào)函數(shù)

const x = ref(0)
const y = ref(0)

// 單個 ref
watch(x, (newValue, oldValue) => {
  console.log(`x is ${newValue}`)
})

// getter 函數(shù)
watch(
  () => x.value + y.value,
  (newValue, oldValue) => {
    console.log(`sum of x + y is: ${newValue}`)
  }
)

// 多個來源組成的數(shù)組
watch([x, () => y.value], ([newX, newY]) => {
  console.log(`x is ${newX} and y is ${newY}`)
})

第一個參數(shù)可以是不同形式的“數(shù)據(jù)源”:它可以是一個 ref (包括計算屬性)、一個響應式對象、一個 getter 函數(shù)、或多個數(shù)據(jù)源組成的數(shù)組

第二個參數(shù)是在發(fā)生變化時要調(diào)用的回調(diào)函數(shù)。這個回調(diào)函數(shù)接受三個參數(shù):新值、舊值,以及一個用于注冊副作用清理的回調(diào)函數(shù)。該回調(diào)函數(shù)會在副作用下一次重新執(zhí)行前調(diào)用,可以用來清除無效的副作用,例如等待中的異步請求。

第三個可選的參數(shù)是一個對象,支持以下這些選項:

  • immediate:在偵聽器創(chuàng)建時立即觸發(fā)回調(diào)。第一次調(diào)用時舊值是 undefined。
  • deep:如果源是對象,強制深度遍歷,以便在深層級變更時觸發(fā)回調(diào)。參考深層偵聽器。
  • flush:調(diào)整回調(diào)函數(shù)的刷新時機。參考回調(diào)的刷新時機及 watchEffect()。
  • onTrack / onTrigger:調(diào)試偵聽器的依賴。參考調(diào)試偵聽器。

源碼實現(xiàn)

  • @issue1 深度遞歸循環(huán)時考慮對象中有循環(huán)引用的問題

  • @issue2 兼容數(shù)據(jù)源為響應式對象和getter函數(shù)的情況

  • @issue3 immediate回調(diào)執(zhí)行時機

  • @issue4 onCleanup該回調(diào)函數(shù)會在副作用下一次重新執(zhí)行前調(diào)用

/**
 * @desc 遞歸循環(huán)讀取數(shù)據(jù)
 * @issue1 考慮對象中有循環(huán)引用的問題
 */
function traversal(value, set = new Set()) {
  // 第一步遞歸要有終結(jié)條件,不是對象就不在遞歸了
  if (!isObject(value)) return value

  // @issue1 處理循環(huán)引用
  if (set.has(value)) {
    return value
  }
  set.add(value)

  for (let key in value) {
    traversal(value[key], set)
  }
  return value
}

/**
 * @desc watch
 * @issue2 兼容數(shù)據(jù)源為響應式對象和getter函數(shù)的情況
 * @issue3 immediate 立即執(zhí)行
 * @issue4 onCleanup:用于注冊副作用清理的回調(diào)函數(shù)。該回調(diào)函數(shù)會在副作用下一次重新執(zhí)行前調(diào)用,可以用來清除無效的副作用,例如等待中的異步請求
 */
// source 是用戶傳入的對象, cb 就是對應的回調(diào)
export function watch(source, cb, { immediate } = {} as any) {
  let getter

  // @issue2
  // 是響應式數(shù)據(jù)
  if (isReactive(source)) {
    // 遞歸循環(huán),只要循環(huán)就會訪問對象上的每一個屬性,訪問屬性的時候會收集effect
    getter = () => traversal(source)
  } else if (isRef(source)) {
    getter = () => source.value
  } else if (isFunction(source)) {
    getter = source
  }else {
    return
  }

  // 保存用戶的函數(shù)
  let cleanup
  const onCleanup = fn => {
    cleanup = fn
  }

  let oldValue
  const scheduler = () => {
    // @issue4 下一次watch開始觸發(fā)上一次watch的清理
    if (cleanup) cleanup()
    const newValue = effect.run()
    cb(newValue, oldValue, onCleanup)
    oldValue = newValue
  }

  // 在effect中訪問屬性就會依賴收集
  const effect = new ReactiveEffect(getter, scheduler) // 監(jiān)控自己構(gòu)造的函數(shù),變化后重新執(zhí)行scheduler

  // @issue3
  if (immediate) {
    // 需要立即執(zhí)行,則立刻執(zhí)行任務
    scheduler()
  }

  // 運行getter,讓getter中的每一個響應式變量都收集這個effect
  oldValue = effect.run()
}

測試代碼

循環(huán)引用

對象中存在循環(huán)引用的情況

const person = reactive({
  name: '柏成',
  age: 25,
  address: {
    province: '山東省',
    city: '濟南市',
  }
})
person.self = person

watch(
  person,
  (newValue, oldValue) => {
    console.log('person', newValue, oldValue)
  }, {
    immediate: true
  },
)

數(shù)據(jù)源

  1. 數(shù)據(jù)源為 ref 的情況,和 immediate 回調(diào)執(zhí)行時機
const x = ref(1)

watch(
  x,
  (newValue, oldValue) => {
    console.log('x', newValue, oldValue)
  }, {
    immediate: true
  },
)

setTimeout(() => {
  x.value = 2
}, 100)
  1. 兼容數(shù)據(jù)源為 響應式對象getter函數(shù) 的情況,和 immediate 回調(diào)執(zhí)行時機
const person = reactive({
  name: '柏成',
  age: 25,
  address: {
    province: '山東省',
    city: '濟南市',
  }
})

// person.address 對象本身及其內(nèi)部每一個屬性 都收集了effect。traversal遞歸遍歷
watch(
  person.address,
  (newValue, oldValue) => {
    console.log('person.address', newValue, oldValue)
  }, {
    immediate: true
  },
)

// 注意!我們在 watch 源碼內(nèi)部滿足了 isFunction 條件
// 此時只有 address 對象本身收集了effect,僅當 address 對象整體被替換時,才會觸發(fā)回調(diào);
// 其內(nèi)部屬性發(fā)生變化并不會觸發(fā)回調(diào)
watch(
  () => person.address,
  (newValue, oldValue) => {
    console.log('person.address', newValue, oldValue)
  }, {
    immediate: true
  },
)

// person.address.city 收集了 effect
watch(
  () => person.address.city,
  (newValue, oldValue) => {
    console.log('person.address.city', newValue, oldValue)
  }, {
    immediate: true
  },
)

setTimeout(() => {
  person.address.city = '青島市'
}, 100)

onCleanup

watch回調(diào)函數(shù)接受三個參數(shù):新值、舊值,以及一個用于注冊副作用清理的回調(diào)函數(shù)(即我們的onCleanup)。該回調(diào)函數(shù)會在副作用下一次重新執(zhí)行前調(diào)用,可以用來清除無效的副作用,例如等待中的異步請求。文章來源地址http://www.zghlxwxcb.cn/news/detail-760482.html

const person = reactive({
  name: '柏成',
  age: 25
})

let timer = 3000
function getData(timer) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(timer)
    }, timer)
  })
}

// 1. 第一次調(diào)用watch的時候注入一個取消的回調(diào)
// 2. 第二次調(diào)用watch的時候會執(zhí)行上一次注入的回調(diào)
// 3. 第三次調(diào)用watch會執(zhí)行第二次注入的回調(diào)
// 后面的watch觸發(fā)會將上次watch中的 clear 置為true
watch(
  () => person.age,
  async (newValue, oldValue, onCleanup) => {
    let clear = false
    onCleanup(() => {
      clear = true
    })

    timer -= 1000
    let res = await getData(timer) // 第一次執(zhí)行2s后渲染2000, 第二次執(zhí)行1s后渲染1000, 最終應該是1000
    if (!clear) {
      document.body.innerHTML = res
    }
  },
)

person.age = 26
setTimeout(() => {
  person.age = 27
}, 0)

到了這里,關于【源碼系列#04】Vue3偵聽器原理(Watch)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 深入與淺談 Vue 中計算屬性和偵聽器的區(qū)別和使用(Vue3版本為例)

    深入與淺談 Vue 中計算屬性和偵聽器的區(qū)別和使用(Vue3版本為例)

    #五一技術創(chuàng)作馬拉松# 計算屬性 computed 和偵聽器 watch 都是 Vue.js 框架中用來響應式更新視圖的重要概念。在 Vue 項目開發(fā)中,這兩個技術點是非常重要的,同時也是 Vue 基礎中不可缺少的知識點。在面試中,計算屬性 computed 和偵聽器 watch 也是經(jīng)常出現(xiàn)的考點,作為前端開發(fā)也

    2024年02月07日
    瀏覽(24)
  • Vue——偵聽器

    目錄 基本示例? 深層偵聽器? 即時回調(diào)的偵聽器? 回調(diào)的觸發(fā)時機? this.$watch()? 停止偵聽器? ? ? ? ?計算屬性允許我們聲明性地計算衍生值。然而在有些情況下,我們需要在狀態(tài)變化時執(zhí)行一些“副作用”:例如更改 DOM,或是根據(jù)異步操作的結(jié)果去修改另一處的狀態(tài)

    2023年04月13日
    瀏覽(24)
  • Vue中watch偵聽器用法

    watch 需要偵聽特定的數(shù)據(jù)源,并在單獨的回調(diào)函數(shù)中執(zhí)行副作用 watch第一個參數(shù)監(jiān)聽源 watch第二個參數(shù)回調(diào)函數(shù)cb(newVal,oldVal) watch第三個參數(shù)一個options配置項是一個對象{ immediate :true //是否立即調(diào)用一次 deep :true //是否開啟深度監(jiān)聽 flush :“pre” // 更新時機 } flush配置項 p

    2024年02月06日
    瀏覽(24)
  • Vue學習-計算屬性和偵聽器

    1、計算屬性的定義和原理 1、定義:要用的屬性不存在,要通過已有屬性計算得來。 2、原理:底層借助了Objcet.defineproperty方法提供的getter和setter。 3、get函數(shù)什么時候執(zhí)行? ??(1) 初次讀取時會執(zhí)行一次。 ??(2)當依賴的數(shù)據(jù)發(fā)生改變時會被再次調(diào)用。 4、優(yōu)勢:與

    2023年04月18日
    瀏覽(28)
  • VUE教程-基礎-計算屬性和偵聽器

    模板內(nèi)的表達式非常便利,但是設計它們的初衷是用于簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。例如: 在這個地方,模板不再是簡單的聲明式邏輯。你必須看一段時間才能意識到,這里是想要顯示變量? message ?的翻轉(zhuǎn)字符串。當你想要在模板中的多

    2024年02月17日
    瀏覽(27)
  • 【Spring Boot系列】- Spring Boot偵聽器Listener

    【Spring Boot系列】- Spring Boot偵聽器Listener

    什么事Web監(jiān)聽器?web監(jiān)聽器就是 Servlet中特殊的類 ,他們能幫助開發(fā)者監(jiān)聽web中的特定事件,比如ServletContext、HttpSession、ServletRequest的創(chuàng)建和銷毀;變量的創(chuàng)建、銷毀和修改等??梢栽谀承﹦幼髑昂笤黾犹幚?,實現(xiàn)監(jiān)控等等。web監(jiān)聽器的使用場景有很多;Spring的監(jiān)聽器是一種

    2024年02月07日
    瀏覽(21)
  • 二、基礎篇 vue計算屬性和偵聽器

    模板內(nèi)的表達式非常便利,但是設計它們的初衷是用于簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。例如: 在這個地方,模板不再是簡單的聲明式邏輯。你必須看一段時間才能意識到,這里是想要顯示變量? message ?的翻轉(zhuǎn)字符串。當你想要在模板中的多

    2024年01月18日
    瀏覽(21)
  • Vue Composition API之偵聽器watch/watchEffect

    Vue Composition API之偵聽器watch/watchEffect

    在日常的開發(fā)中,很多時候我們需要去對一些狀態(tài)進行監(jiān)聽,比如當顯示學生的成績列表時,我們使用一個學生的學號student_num作為請求成績的參數(shù),如果沒有監(jiān)聽機制,當學號student_num改變時,我們需要依賴用戶的操作去刷新成績。但是有了偵聽器,我們可以通過偵聽器去監(jiān)

    2024年02月08日
    瀏覽(22)
  • 【vue2】計算屬性(computed)與偵聽器(watch)詳解

    【vue2】計算屬性(computed)與偵聽器(watch)詳解

    ??博???????主: 初映CY的前說(前端領域) ??個人信條: 想要變成得到,中間還有做到! ??本文核心: 計算屬性與偵聽屬性的用法 目錄( 文末有給大家準備好的Xmind思維導圖 ) 一、計算屬性computed ①默認get()方法,僅是獲取值 ②不僅僅是獲取值,還具有修改屬性功能

    2024年01月16日
    瀏覽(20)
  • 微信小程序?qū)崿F(xiàn)頁面數(shù)據(jù)偵聽器,類似vue的watch

    既然小程序的組件已經(jīng)有Observer功能,那為什么還要手寫watch功能呢? Observer只能在Component中使用,沒法在Page中使用。若是想在Page中監(jiān)控某一數(shù)據(jù)的變化,Observer做不到。 Observer屬于小程序的新功能,只能在高版本微信使用,低版本微信無法使用。公司的小程序就因為使用了

    2024年02月03日
    瀏覽(27)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包