模擬實現Vue2-Vue3響應式更新

Vue2作為 MVVM框架

/*
Vue2 通過 Object.defineProperty 監聽、挾持數據,實現響應式
并通過 Dep(依賴收集器) 和 Watcher 實現依賴收集,通知視圖更新
*//*
但是 Vue2用Object.defineProperty 無法監聽新增屬性、無法監聽數組索引變化、無法監聽數組長度變化
*/// 依賴收集器
class Dep {constructor() {this.subs = [];}addSub(sub) {this.subs.push(sub);}notify() {this.subs.forEach(sub => sub.update());}
}Dep.target = null;// Observer 數據劫持
// 激活 get,set 函數
function Vue2Reactive(obj, key, val) {const dep = new Dep();Object.defineProperty(obj, key, {get() {// 依賴收集if (Dep.target) {dep.addSub(Dep.target);}return val;},set(newVal) {if (newVal !== val) {val = newVal;// 通知視圖更新dep.notify();}}});
}
// 通過 Object.keys(obj) + forEach 遍歷對象的所有屬性都進行激活
function activeAllProperties(obj) {if (typeof obj !== 'object' || obj === null) return;Object.keys(obj).forEach(key => {Vue2Reactive(obj, key, obj[key]);});
}// Watcher 類
class Watcher {constructor(vm, key, callback) {this.vm = vm;this.key = key;this.callback = callback;this.value = this.get();}get() {Dep.target = this;const value = this.vm[this.key];Dep.target = null;return value;}update() {const newValue = this.vm[this.key];if (newValue !== this.value) {this.value = newValue;this.callback(newValue);}}
}

Vue3

Vue3不再強調 MVVM,其底層是由 TypeScript 編寫的,將 Object.defineProperty 換成 Proxy 實現響應式系統,彌補了前者的缺陷,使用編譯器將模版換成高效的渲染函數,并通過虛擬 DOM 和調度系統實現高性能更新

/* 為什么要用 Reflect
統一為函數式寫法,符合面向對象
報錯不會中斷,而是返回 false(比如只讀的時候)
通過 receiver 參數可以指定 this上下文
*/const bucket = new WeakMap(); // 用于依賴收集function Vue3Reactive(obj) {return new Proxy(obj, {get(target, key, receiver) {track(target, key); // 收集依賴return Reflect.get(target, key, receiver);},set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver);trigger(target, key); // 觸發更新return result;}});
}// 收集依賴函數
function track(target, key) {if (!activeEffect) return; // 如果沒有激活的 effect,直接返回let depsMap = bucket.get(target); // 獲取 target 的依賴映射if (!depsMap) bucket.set(target, (depsMap = new Map()));let deps = depsMap.get(key); // 獲取 key 的依賴集合if (!deps) depsMap.set(key, (deps = new Set())); deps.add(activeEffect); // 將當前激活的 effect 添加到依賴集合
}// 觸發更新函數
function trigger(target, key) {const depsMap = bucket.get(target); // 獲取 target 的依賴映射if (!depsMap) return; // 如果沒有依賴,直接返回const deps = depsMap.get(key); // 獲取 key 的依賴集合if (deps) deps.forEach(fn => fn()); // 遍歷依賴集合,執行每個依賴的函數
}// 示例
let activeEffect;
function effect(fn) {activeEffect = fn;fn(); // 立即執行一次activeEffect = null;
}const state = Vue3Reactive({ count: 0 });effect(() => {console.log('count is:', state.count); // 依賴收集
});state.count++; // 觸發更新

實際上,Vue3在底層上還做了許多細節的優化,比如惰性代理節省操作、微任務批次處理節流更新、自動對依賴進行清理等等

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

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

相關文章

一文理解鋰電池充電、過放修復與電量測量:從原理到實戰

一、為什么要看這篇文章? 手機電量突然從20%跳到0%?電動車冬天續航腰斬?18650過放后還能救嗎? 本文用一張思維導圖一張表格一段口訣,一次性講透鋰電池的充電四階段、過放修復全方案、電量測量底層原理,并給…

【爬蟲】01 - 爬蟲原理及其入門

爬蟲01 - 爬蟲原理及其入門 文章目錄爬蟲01 - 爬蟲原理及其入門一:爬蟲原理1:爬蟲的優勢?2:爬蟲的核心庫3:經典舉例4:合規問題一:爬蟲原理 學習爬蟲之前前置知識需要了解這些: 我的HTTP介紹, 了…

React對于流式數據和非流式數據的處理和優化

React 在處理流式數據和非流式數據時,可以借助其組件模型、狀態管理以及 React 18 引入的并發特性來實現高效的數據處理與渲染優化。 文章目錄一、流式數據(Streaming Data)1. 定義2. 常見來源3. 處理方式使用 useState / useReducer 管理狀態…

3、Vue 中使用 Cesium 實現可拖拽點標記及坐標實時顯示功能

在 Cesium 地圖開發中,實現點標記的拖拽交互并實時顯示坐標信息是一個常見的需求。本文將詳細介紹如何在 Vue 框架中使用 Cesium 的 Primitive 方式創建點標記,并實現拖拽功能及坐標提示框跟隨效果。先看效果圖功能實現概述我們將實現的功能包括&#xf…

Anthropic:從OpenAI分支到AI領域的領軍者

自2021年由前OpenAI高管Dario和Daniela Amodei創立以來,Anthropic已迅速崛起為人工智能(AI)領域的重要力量。 公司專注于開發安全、可控且具備深度推理能力的AI系統,其Claude系列模型在生成式AI領域取得了顯著成就。 此外&#xf…

前端開發中的輸出問題

前端開發中的輸出問題:console.log輸出[object Object]在前端開發中,一個常見問題是使用console.log輸出對象時顯示為[object Object],而不是對象的詳細內容。這通常發生在開發者試圖直接打印對象時,瀏覽器默認只顯示對象的字符串…

DSSA(Domain-Specific Software Architecture)特定領域架構

DSSA(Domain-Specific Software Architecture) 定義:針對特定應用領域設計的可復用軟件架構,為領域內產品族提供統一基礎。 目標: ? 最大化復用(需求/設計/代碼)? 保證系統一致性? 降低開發成…

單調棧單調隊列【算法進階】

這周學完之后最大的收獲就是單調棧和單調隊列了!!!感覺好厲害能把時間復雜度瞬間壓縮為O(N),不行我必須再紀念一下這么美妙的算法!!! 單調棧問題: 如果題目要求一個元素左邊或右邊…

C++編程基礎

編程題一問題分析 題目要求使用 n 根小木棒,按照特定的方式排列,形成一個數字。具體規則如下: 每個數字由小木棒組成,例如: 1 需要 2 根小木棒。0 需要 6 根小木棒。其他數字(如 2, 3, 4, 5, 6, 7, 8, 9&am…

張量拼接操作

一.前言本章節來介紹一下張量拼接的操作,掌握torch.cat torch.stack使?,張量的拼接操作在神經?絡搭建過程中是?常常?的?法,例如: 在后?將要學習到的殘差?絡、注意?機 制中都使?到了張量拼接。二.torch.cat 函數的使用torch.cat 函數…

Dify 連接本地 SpringAI MCP Server

Dify 連接本地 SpringAI MCP server 連接 MCP server 的方式大致有兩種,一種是基于 stdio,一種是基于 sse,如果對于穩定和性能好的方案的話,sse 要比 stdio 好的多,所以本文采用的是基于 sse 和 Spring AI 部署本地 MC…

基于 Python 的數據分析技術綜述

先說一點個人的看法“”MDX、OLAP(Mondrian)技術更適合構建面向業務用戶的標準化分析產品,尤其當產品需要滿足以下特點時:分析維度固定(如時間、區域、產品類別);需支持高并發查詢(如…

Live555-RTSP服務器

RTSP Server創建 RTSP服務器初始化: RTSPServer::createNew->new RTSPServer::RTSPServer->GenericMediaServer::GenericMediaServer->turnOnBackgroundReadHandling(IPV4sock/IPV6sock,incomingConnectionHandlerIPv4)如上流程,創建RTSP服務器…

Redis Stack擴展功能

Redis JSONRedisJSON是Redis的一個擴展模塊,它提供了對JSON數據的原生支持。常用操作:-- 設置一個JSON數據JSON.SET user $ {"name":"loulan","age":18}## key是user,value就是一個JSON數據。其中$表示JSON數據…

Takebishi旗下智能硬件網關產品devicegateway詳細介紹

一、產品概述 DeviceGateway是由日本Takebishi公司研發的一款專業工業物聯網(IIoT)硬件網關產品,專為實現現場工業設備與云端平臺、IT系統之間的高效、安全數據傳輸而設計。作為一款可靠的硬件網關,DeviceGateway具有即插即用、穩…

單向鏈表反轉 如何實現

單向鏈表反轉的實現方法 ? https://www.zhihu.com/question/441865393/answer/3208578798 ? 單向鏈表反轉是數據結構中的經典問題,在面試和實際開發中經常遇到。以下是 多種實現方式(包括遞歸和迭代),以 Go 語言為例。1. 單向鏈…

php+vue+Laravel音樂媒體播放及周邊產品運營平臺-nodejs-計算機畢業設計

目錄具體實現截圖課程項目技術路線開發技術介紹設計思路流程PHP核心代碼部分展示詳細視頻演示/源碼獲取##項目介紹網絡技術的廣泛應用顯著地推動了生活服務的信息化進程。結合音樂流媒體與周邊產品的運營需求,構建一套音樂媒體播放及周邊產品運營平臺,成…

Python爬蟲實戰:研究xlwt 和 xlrd 庫相關技術

1. 引言 1.1 研究背景與意義 隨著電子商務的快速發展,電商平臺積累了海量的商品數據。如何從這些數據中提取有價值的信息,為商家提供決策支持,成為電商領域的重要研究方向。傳統人工采集和分析數據的方式效率低下,且容易出現錯誤。自動化數據采集與分析系統能夠通過爬蟲技…

【QGC】深入解析 QGC 配置管理

引言 在軟件開發中,配置管理是一項至關重要的任務,它能幫助我們靈活地管理應用程序的各種參數和設置。QGroundControl(QGC)作為一款強大的開源無人機地面站軟件,其配置管理系統設計精巧,值得我們深入學習。…

ChatGPT,從規則到強化學習

要了解 ChatGPT(Chat Generative Pre-training Transformer),我們不得不先看看 NLP 自然語言處理(Natural Language Processing)。因為 ChatGPT 屬于 NLP 領域,而 NLP 則又是人工智能的一個分支。 那么什么…