欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue?3?effect作用與原理解析

 更新時(shí)間:2025年02月07日 08:55:11   作者:啊哈哈哈哈哈h  
Vue3的Effect是其響應(yīng)式系統(tǒng)的核心,負(fù)責(zé)依賴追蹤和自動(dòng)響應(yīng),它通過(guò)ReactiveEffect類封裝副作用邏輯,實(shí)現(xiàn)依賴收集和觸發(fā)更新,本文介紹vue?3?effect作用與原理解析,感興趣的朋友一起看看吧

Vue 3 的 Effect(副作用) 是整個(gè)響應(yīng)式系統(tǒng)的核心機(jī)制,負(fù)責(zé)管理依賴追蹤和響應(yīng)式觸發(fā)。理解其作用和原理對(duì)掌握 Vue 的底層機(jī)制至關(guān)重要。

一、核心作用

1. 依賴追蹤(Dependency Tracking)

  • 自動(dòng)跟蹤響應(yīng)式數(shù)據(jù)在副作用函數(shù)中的使用。

示例代碼

import { reactive, effect } from 'vue'
const obj = reactive({ count: 0 })
effect(() => {
  console.log(`count is: ${obj.count}`)
})
  • 當(dāng)首次執(zhí)行 effect 時(shí),函數(shù) () => console.log(...) 會(huì)被運(yùn)行。
  • 觸發(fā) obj.count 的 get 操作,觸發(fā)依賴收集(將當(dāng)前 effect 關(guān)聯(lián)到 obj.count)。

2. 自動(dòng)響應(yīng)(Automatic Re-run)

當(dāng)響應(yīng)式數(shù)據(jù)的依賴變化時(shí),自動(dòng)重新執(zhí)行副作用函數(shù):

obj.count++  // 觸發(fā)依賴更新,控制臺(tái)打印 "count is: 1"

3. 支撐高級(jí) API

  • computedwatch、組件渲染函數(shù)等底層都依賴于 effect 實(shí)現(xiàn)。

二、實(shí)現(xiàn)原理

1. 核心類:ReactiveEffect

Vue 3 用 ReactiveEffect 類封裝副作用邏輯,簡(jiǎn)化后的源碼結(jié)構(gòu)如下:

class ReactiveEffect<T = any> {
  // 當(dāng)前 effect 的所有依賴項(xiàng)(其他響應(yīng)式對(duì)象)
  deps: Dep[] = []
  // 構(gòu)造函數(shù)參數(shù)
  constructor(
    public fn: () => T,            // 副作用函數(shù)
    public scheduler?: () => void  // 調(diào)度函數(shù)(控制重新執(zhí)行方式)
  ) {}
  // 運(yùn)行副作用(觸發(fā)依賴收集)
  run() {
    activeEffect = this // 標(biāo)記當(dāng)前正在運(yùn)行的 effect
    try {
      return this.fn()
    } finally {
      activeEffect = undefined
    }
  }
  // 停止偵聽(tīng)
  stop() { /* 從所有依賴中移除自身 */ }
}

2. 依賴收集流程(Track)

數(shù)據(jù)結(jié)構(gòu)

type Dep = Set<ReactiveEffect>    // 依賴集合
type TargetMap = WeakMap<Object, Map<string, Dep>> // 全局依賴存儲(chǔ)
  • 觸發(fā)時(shí)機(jī):響應(yīng)式數(shù)據(jù)的 get 操作觸發(fā)時(shí)。
  • 流程

    根據(jù)響應(yīng)式對(duì)象 (target) 和鍵 (key) 找到存入 targetMap 的依賴集合 (dep)。

    將當(dāng)前活躍的 activeEffect 添加到 dep 中。

    同時(shí)將 dep 加入 activeEffect.deps(反向記錄,用于 cleanup)。

3. 觸發(fā)更新(Trigger)

  • 觸發(fā)時(shí)機(jī):響應(yīng)式數(shù)據(jù)的 set 操作時(shí)。
  • 流程

    根據(jù) target 和 key 從 targetMap 獲取對(duì)應(yīng)的 dep 集合。

    遍歷 dep 中所有 effect

    • 如果有 scheduler(如 computed),執(zhí)行調(diào)度器(優(yōu)化性能)。
    • 否則直接執(zhí)行 effect.run()

4. 調(diào)度器(Scheduler)

允許控制 effect 如何重新執(zhí)行:

effect(() => {
  console.log(obj.count)
}, {
  scheduler(effect) { 
    // 如將 effect 推入微任務(wù)隊(duì)列中異步執(zhí)行
    queueMicrotask(effect.run) 
  }
})
  • 應(yīng)用場(chǎng)景:
    • watch 的異步批處理更新。
    • computed 的值懶更新。

三、關(guān)鍵優(yōu)化設(shè)計(jì)

1. 嵌套 Effect 棧

用棧結(jié)構(gòu) effectStack 跟蹤嵌套的 effect:

function run() {
  if (!effectStack.includes(this)) {
    try {
      effectStack.push((activeEffect = this))
      return this.fn()
    } finally {
      effectStack.pop()
      activeEffect = effectStack[effectStack.length - 1]
    }
  }
}
  • 解決問(wèn)題:組件嵌套時(shí)的依賴關(guān)系混亂。

2. Cleanup 機(jī)制

每次 effect 執(zhí)行前清理舊依賴:

function run() {
  cleanup(this) // 清理之前收集的舊依賴
  // ...然后重新收集新依賴
}
  • 解決問(wèn)題:動(dòng)態(tài)分支邏輯導(dǎo)致的無(wú)效依賴(如 v-if 切換導(dǎo)致的條件依賴)。

3. Lazy 執(zhí)行

可配置不立即執(zhí)行 effect:

const runner = effect(fn, { lazy: true })
runner() // 手動(dòng)執(zhí)行
  • 應(yīng)用場(chǎng)景computed 屬性初始化時(shí)延遲計(jì)算。

四、與 Vue 各組件的關(guān)聯(lián)

1. 組件渲染

組件 render 函數(shù)被包裹在 effect 中:

function setupRenderEffect(instance) {
  effect(() => {
    const subTree = instance.render.call(instance.proxy)
    patch(instance.subTree, subTree)
    instance.subTree = subTree
  }, { scheduler: queueJob }) // 異步更新隊(duì)列
}

2. Computed 實(shí)現(xiàn)

computed 通過(guò) effect + 調(diào)度器實(shí)現(xiàn)懶更新:

const computedRef = new ComputedRefImpl(
  getter,
  () => { // 調(diào)度器
    if (!this._dirty) {
      this._dirty = true
      trigger(this, 'set', 'value')
    }
  }
)

3. Watch API

watch 基于 effect 的調(diào)度器實(shí)現(xiàn)異步回調(diào):

function watch(source, cb, { flush } = {}) {
  let scheduler
  if (flush === 'sync') {
    scheduler = cb
  } else { // 'post' 或其他默認(rèn)情況
    scheduler = () => queuePostFlushCb(cb)
  }
  effect(() => traverse(source), { scheduler })
}

五、與 Vue 2 的對(duì)比

特性Vue 2 (Watcher)Vue 3 (Effect)
依賴追蹤通過(guò)遍歷數(shù)據(jù)觸發(fā) getter通過(guò) Proxy/Reflect 自動(dòng)追蹤
更新粒度依賴組件級(jí)檢查基于精確依賴的靶向更新
性能優(yōu)化需手寫(xiě) pureComputed 等內(nèi)置自動(dòng)的依賴清理和調(diào)度機(jī)制
內(nèi)存管理易產(chǎn)生內(nèi)存泄漏(舊 Dep 引用問(wèn)題)通過(guò) WeakMap 自動(dòng)釋放無(wú)用依賴

六、源碼流程圖解

+---------------------+
|   Reactive Object   |
+----------+----------+
           │ 訪問(wèn)屬性時(shí)
           ▼
+---------------------+
|   觸發(fā) get 代理     +----→ track(target, key)
+---------------------+         │
           ▲                    ▼ 存儲(chǔ)依賴關(guān)系
           │          +---------------------+
           +----------+    targetMap        |
                      | (WeakMap結(jié)構(gòu))        |
                      +---------+-----------+
                                │
                                ▼
                      +---------------------+
                      |   depsMap (Map)     |
                      | (key → Dep Set)      |
                      +---------+-----------+
                                │
                                ▼
                      +---------------------+
                      |   dep (Set)         |
                      | (存儲(chǔ)所有關(guān)聯(lián)的 effect)|
                      +---------------------+

總結(jié)

Vue 3 的 effect 通過(guò)以下機(jī)制成為響應(yīng)式系統(tǒng)的核心:

  • Proxy 依賴收集:精確追蹤響應(yīng)式數(shù)據(jù)的使用。
  • 調(diào)度器控制:提供靈活的回調(diào)執(zhí)行方式。
  • 內(nèi)存安全:通過(guò) WeakMap 自動(dòng)管理依賴。
  • 框架級(jí)優(yōu)化:支持組件渲染、計(jì)算屬性、watch 等核心功能。

到此這篇關(guān)于vue 3 effect作用與原理的文章就介紹到這了,更多相關(guān)vue 3 effect作用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue項(xiàng)目中打包優(yōu)化的四種方法詳解

    Vue項(xiàng)目中打包優(yōu)化的四種方法詳解

    最近入職了新公司,接手了一個(gè)新拆分出來(lái)的Vue項(xiàng)目,針對(duì)該項(xiàng)目做了個(gè)打包優(yōu)化,下面這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中打包優(yōu)化的四種方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • 淺談關(guān)于iview表單驗(yàn)證的問(wèn)題

    淺談關(guān)于iview表單驗(yàn)證的問(wèn)題

    這篇文章主要介紹了淺談關(guān)于iview表單驗(yàn)證的問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • vue中后端做Excel導(dǎo)出功能返回?cái)?shù)據(jù)流前端的處理操作

    vue中后端做Excel導(dǎo)出功能返回?cái)?shù)據(jù)流前端的處理操作

    這篇文章主要介紹了vue中后端做Excel導(dǎo)出功能返回?cái)?shù)據(jù)流前端的處理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • electron最小化托盤(pán)設(shè)置

    electron最小化托盤(pán)設(shè)置

    本文主要介紹了electron最小化托盤(pán)設(shè)置,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • element-ui 表格實(shí)現(xiàn)單元格可編輯的示例

    element-ui 表格實(shí)現(xiàn)單元格可編輯的示例

    下面小編就為大家分享一篇element-ui 表格實(shí)現(xiàn)單元格可編輯的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • vue data有值,但是頁(yè)面{{}} 取不到值的解決

    vue data有值,但是頁(yè)面{{}} 取不到值的解決

    這篇文章主要介紹了vue data有值,但是頁(yè)面{{}} 取不到值的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • Vue前端書(shū)寫(xiě)規(guī)范大全(非常詳細(xì)!)

    Vue前端書(shū)寫(xiě)規(guī)范大全(非常詳細(xì)!)

    在團(tuán)體開(kāi)發(fā)項(xiàng)目中,為了團(tuán)隊(duì)所有成員書(shū)寫(xiě)可維護(hù)的代碼,而不是一次性的代碼,讓團(tuán)隊(duì)當(dāng)中其他人看你的代碼能一目了然,下面這篇文章主要給大家介紹了關(guān)于Vue前端書(shū)寫(xiě)規(guī)范的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • vue中使用props傳值的方法

    vue中使用props傳值的方法

    這篇文章主要介紹了vue中使用props傳值的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • vite+vue3項(xiàng)目中使用SVG方式

    vite+vue3項(xiàng)目中使用SVG方式

    這篇文章主要介紹了vite+vue3項(xiàng)目中使用SVG方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • vue中el-table樹(shù)狀表格末行合計(jì)實(shí)現(xiàn)

    vue中el-table樹(shù)狀表格末行合計(jì)實(shí)現(xiàn)

    本文主要介紹了vue中el-table樹(shù)狀表格末行合計(jì)實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11

最新評(píng)論