Vue3源碼reactivity響應式篇之EffectScope

概述

EffectScope是Vue3中一個響應式系統的輔助類,用于管理副作用(effect)的作用域。它可以幫助我們更好地組織和管理多個effect,便于一起停止或暫停以及恢復,避免了全局狀態的污染和管理的復雜性。

每一個vue組件的實例上都會掛載一個EffectScope的實例scope,該掛載動作會在createComponentInstance中進行。在組件被激活掛載時,會調用scope.on()方法,將當前作用域設置為活動作用域;而在組件被卸載或者銷毀時,會調用scope.stop()方法。

源碼解析

let activeEffectScope;class EffectScope {constructor(detached = false) {this.detached = detached; // 表示該作用域是否獨立(不嵌套在父作用域中)this._active = true; //表示作用域是否激活this._on = 0; // 一個計數器,用于記錄當前作用域被開啟的次數(通過on方法)this.effects = []; // 存儲屬于該作用域的effectthis.cleanups = []; // 存儲清理函數,當作用域停止時會執行這些清理函數this._isPaused = false; // 表示作用域是否被暫停this.parent = undefined; //指向父作用域this.scopes = undefined; //存儲嵌套的子作用域this.index = undefined; // 在父作用域的scopes數組中的索引this.prevScope = undefined; // 在調用 on 方法時,用于保存當前的activeEffectScope,以便在off時恢復,上一個作用域(用于作用域鏈)this.parent = activeEffectScope; //將父作用域指向激活的作用域if (!detached && activeEffectScope) {// 若該作用域不獨立且當前存在激活的作用域,則將該作用域存放到激活作用域(父作用域)的子作用域的末尾,并設置該作用域的索引this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(this) - 1;}}// 暫停作用域pause() {if (this._active) {this._isPaused = true;let i, l;if (this.scopes) {for (i = 0, l = this.scopes.length; i < l; i++) {this.scopes[i].pause();}}for (i = 0, l = this.effects.length; i < l; i++) {this.effects[i].pause();}}}// 恢復作用域resume() {if (this._active) {if (this._isPaused) {this._isPaused = false;let i, l;if (this.scopes) {for (i = 0, l = this.scopes.length; i < l; i++) {this.scopes[i].resume();}}for (i = 0, l = this.effects.length; i < l; i++) {this.effects[i].resume();}}}}// 在作用域內運行函數run(fn) {if (this._active) {const currentEffectScope = activeEffectScope;try {activeEffectScope = this;return fn();} finally {activeEffectScope = currentEffectScope;}}}// 開啟作用域on() {if (++this._on === 1) {this.prevScope = activeEffectScope;activeEffectScope = this;}}// 關閉作用域off() {if (this._on > 0 && --this._on === 0) {activeEffectScope = this.prevScope;this.prevScope = void 0;}}// 停止作用域stop(fromParent) {if (this._active) {this._active = false;let i, l;for (i = 0, l = this.effects.length; i < l; i++) {this.effects[i].stop();}this.effects.length = 0;for (i = 0, l = this.cleanups.length; i < l; i++) {this.cleanups[i]();}this.cleanups.length = 0;if (this.scopes) {for (i = 0, l = this.scopes.length; i < l; i++) {this.scopes[i].stop(true);}this.scopes.length = 0;}if (!this.detached && this.parent && !fromParent) {const last = this.parent.scopes.pop();if (last && last !== this) {this.parent.scopes[this.index] = last;last.index = this.index;}}this.parent = void 0;}}
}
核心方法

核心方法主要分為三類:作用域控制(pause/resume/stop)、作用域運行(run)和作用域激活(on/off)

作用域控制
  • pause

pause方法就是用于暫停作用域及其所有子作用域和副作用。先是判斷作用域是否處于激活狀態,若是激活狀態,則修改作用域的暫停狀態this._isPaused,改為true,然后遍歷子作用域和副作用數組,調用其stop方法實現暫停。

  • resume

resume方法用于暫停狀態的作用域及其所有子作用域和副作用。和pause方法是相反的操作,會修改this.isPausedfalse,遍歷調用所有子作用域和副作用的resume方法。

  • stop

stop方法用于停止作用域:清理所有副作用和子作用域,并且從父作用域中移除自身。

stop方法會停止所有effect,執行所有cleanups,并遞歸停止所有子作用域。如果該作用域不是獨立的且由副作用域,并且不是由副作用域觸發的停止,則從副作用域的scopes數組中移除自己,并調整數組。

作用域運行
  • run

run方法用于在該作用域內運行函數,這樣函數內創建的effect會自動注冊到該作用域中。主要就是將該作用域切換為激活作用域,然后執行fn,最后恢復激活作用域為之前的。

作用域激活
  • on

on方法用于激活作用域,就是增加計數器,若計數器增加后等于 1,則將該作用域作為激活作用域。

  • off

off方法和on方法相對,用于關閉作用域,減少計數器,若計數器大于 0,且減少后等于0,則恢復激活作用域為前值。

通過on/off方法,可以臨時切換當前激活的作用域,這樣可以實現在onoff切換之間創建effect會注冊到該作用域中。

輔助方法

EffectScope類相關的三個輔助方法:effectScopegetCurrentScopeonScopeDispose

  • effectScope

effectScope方法就是返回EffectScope的實例對象。

function effectScope(detached) {return new EffectScope(detached);
}
  • getCurrentScope

getCurrentScope方法用于獲取當前活躍(激活)的作用域

function getCurrentScope() {return activeEffectScope;
}
  • onScopeDispose

onScopeDispose方法會判斷若當前作用域存在,則將函數fn注入到作用域的清理數組cleanups中。

function onScopeDispose(fn, failSilently = false) {if (activeEffectScope) {activeEffectScope.cleanups.push(fn);}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98461.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98461.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98461.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL 日志全解析:Binlog/Redo/Undo 等 5 類關鍵日志的配置、作用與最佳實踐

1 二進制日志&#xff08;Binlog&#xff09;&#xff1a;配置與核心作用 Binlog 是 MySQL 中跨存儲引擎的核心日志&#xff0c;記錄所有數據修改操作&#xff0c;主要用于主從復制、數據備份恢復與跨庫遷移。 1.1 Binlog 核心操作 開啟 Binlog 若需開啟 Binlog&#xff0c;需在…

springboot 之 HTML與圖片生成 (2)

前言 之前寫了一篇html轉圖片的 文章&#xff0c;使用中文時會出現亂碼情況&#xff0c;后來又從網上找了下信息&#xff0c;這篇主要介紹下另一個轉換庫。 依賴 <!-- 用于將html轉圖片--><dependency><groupId>gui.ava</groupId><artifactId>…

計算機組成原理:計算機的分類

&#x1f4cc;目錄&#x1f5a5;? 計算機組成原理&#xff1a;計算機的分類——從架構到應用的全景梳理一、按處理數據類型分類&#xff1a;從“數字”到“混合”的演進&#xff08;一&#xff09;數字計算機&#xff1a;離散數據的“精準管家”1. 核心原理2. 關鍵優勢3. 典型…

數據結構——單向循環鏈表代碼(補充)

在此前的文章中&#xff08;鏈接如下&#xff09;&#xff0c;只有單向鏈表的代碼&#xff0c;接下來我們來寫單向循環鏈表&#xff0c;并用其實現一個簡單的學生信息鏈表https://blog.csdn.net/2301_80406299/article/details/151157051?spm1011.2415.3001.10575&sharefr…

【Python自動化】 21.2 Pandas 讀取 Excel 時的 dtype 參數完全指南

一、dtype 參數概述 dtype 參數用于指定列的數據類型&#xff0c;在讀取 Excel 時非常重要&#xff0c;可以&#xff1a; 提高內存效率避免自動類型推斷錯誤確保數據一致性提升讀取性能 二、基本用法 1. 基礎語法 import pandas as pd# 指定列數據類型 df pd.read_excel(data.…

gtest全局套件的測試使用

gtest全局套件的測試使用 #include <iostream> #include "gtest/gtest.h" #include <unordered_map>class MyEnvironment: public testing::Environment {public:virtual void SetUp() override{std::cout<<"單元測試前的環境初始化&#xff…

【系統分析師】第7章-基礎知識:軟件工程(核心總結)

更多內容請見: 備考系統分析師-專欄介紹和目錄 文章目錄 一、軟件工程的基本概念 1.1 定義與意義 1.2 軟件工程的基本原則 1.3 核心定義與邊界 1.4 四大核心原則 1.5 三大核心目標 二、軟件生命周期 2.1 定義與階段劃分 2.2 軟件生命周期模型 三、軟件開發方法 3.1 結構化方法…

量化基金從小白到大師 - 金融數據獲取大全:從免費API到Tick級數據實戰指南

量化基金從小白到大師 - 金融數據獲取大全&#xff1a;從免費API到Tick級數據實戰指南 各位&#xff0c;今天咱們要啃一塊硬骨頭——金融數據獲取。別看這話題基礎&#xff0c;它可是整個量化大廈的地基&#xff0c;地基不穩&#xff0c;再牛的策略都得塌房。我見過太多人&…

構建一個“會思考”的房地產數據獲取腳本

—— 跨界思維&#xff1a;從認知自適應到房源信息監測 一、認知科學視角&#xff1a;什么是“會思考” 在心理學與認知科學中&#xff0c;所謂“會思考”&#xff0c;并不是指抽象的哲學推理&#xff0c;而是指個體能在復雜環境中不斷調整行動策略。 比如&#xff0c;出行時如…

JavaScript的庫簡介

JavaScript擁有豐富的庫生態系統,類似于Python的requests、numpy或C++的Boost。這些庫分為兩大類:前端庫(如React、Vue)和后端/工具庫(如Lodash、Axios)。以下是幾個核心庫的介紹與用法示例。 常用JavaScript庫分類 前端UI庫 React:Facebook開發的組件化庫,用于構建用…

【無GGuF版本】如何在Colab下T4運行gpt-oss 20B

OpenAI發布了gpt-oss 120B和20B版本。這兩個模型均采用Apache 2.0許可證。 特別說明的是&#xff0c;gpt-oss-20b專為低延遲及本地化/專業化場景設計&#xff08;210億總參數&#xff0c;36億活躍參數&#xff09;。 由于模型采用原生MXFP4量化訓練&#xff0c;使得20B版本即…

LeetCode - LCR 179. 查找總價格為目標值的兩個商品

題目 https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/submissions/660817798/ 思路 解法1是暴力解法&#xff0c;從第一個開始和后面的相加 暴力枚舉慢就慢在&#xff0c;這個遞增數組是排序好的數組&#xff0c;已經是有序的&#xff0c;暴力解法沒有利用這…

UI自動化測試Python + Selenium + WinAppDriver( Windows 桌面應用)落地(一)環境搭建

最近公司要求為Windows 端桌面應用進行UI自動化測試,之前都是針對web端進行的UI自動化測試或者在早期使用的是QTP(Quick Test Professional)做PC端的UI自動化測試,而基于"經費"緊張,優先選擇開源的工具,所以選擇了selenium + WinAppDriver來實現。 首先,整理…

基于OpenCV的銀行卡號識別系統:從原理到實現

引言在現代金融科技應用中&#xff0c;銀行卡號的自動識別是一項重要技術。本文將詳細介紹如何使用Python和OpenCV庫構建一個完整的銀行卡號識別系統。該系統能夠從銀行卡圖像中提取卡號信息&#xff0c;并根據卡號首數字判斷銀行卡類型。技術棧?OpenCV: 計算機視覺庫&#xf…

概率論第三講——多維隨機變量及其分布

文章目錄考綱n維隨機變量及其分布函數聯合分布函數邊緣分布函數二維離散型隨機變量的概率分布、邊緣分布和條件分布二維連續型隨機變量的概率密度、邊緣概率密度和條件概率密度常見的二位分布二維均勻分布二維正態分布隨機變量的相互獨立性概念相互獨立的充要條件相互獨立的性質…

純軟件實現電腦屏幕錄制/存儲到硬盤錄像機/onvif模擬器/onvif虛擬監控/綠色版雙擊開箱即用

一、前言說明 在銀行、超市、考試中心、工控系統、網課教學、居家辦公等場景中&#xff0c;傳統監控攝像頭難以清晰錄制電腦屏幕內容&#xff0c;導致關鍵操作無法有效追溯。為解決這一難題&#xff0c;我們推出了一套純軟件實現的電子屏幕監控方案&#xff0c;徹底取代依賴硬…

【算法--鏈表】86.分割鏈表--通俗講解

一、題目是啥?一句話說清 給你一個鏈表和一個值 x,把鏈表分成兩部分:所有小于 x 的節點都放在大于或等于 x 的節點之前,并且保持節點原來的相對順序。 示例: 輸入:head = [1,4,3,2,5,2], x = 3 輸出:[1,2,2,4,3,5](所有小于3的節點1、2、2都在大于等于3的節點4、3、5…

707, 設計鏈表, LinkedList, 單鏈表, Dummy Head, C++

目錄 題意速覽解題思路與設計要點C 代碼實現&#xff08;單鏈表 虛擬頭結點&#xff09;時間復雜度與空間復雜度常見坑位與邊界用例對比&#xff1a;雙鏈表如何優化單元測試樣例&#xff08;可直接粘貼運行&#xff09;總結 題意速覽 設計一個支持如下操作的鏈表&#xff1a…

NAS自建筆記服務leanote2

leanote2(GitHub - wiselike/leanote2: leanote2, 適用于NAS自建的筆記服務) 是一個開源的在線筆記應用程序&#xff0c;繼承自原 leanote 項目。向原 leanote 的開發者表示深深的感謝與尊重&#xff0c;正是他們的辛勤付出奠定了這個優秀的筆記平臺的基礎。 但由于 leanote 項…

模型剪枝----ResNet18剪枝實戰

剪枝 模型剪枝&#xff08;Model Pruning&#xff09; 是一種 模型壓縮&#xff08;Model Compression&#xff09; 技術&#xff0c;主要思想是&#xff1a; 深度神經網絡里有很多 冗余參數&#xff08;對預測結果貢獻很小&#xff09;。 通過去掉這些冗余連接/通道/卷積核&am…