深入淺出:Vue2 數據劫持原理剖析

目錄

一、什么是數據劫持?

二、核心 API:Object.defineProperty

三、Vue2 中的數據劫持實現

1. 對象屬性的劫持

2. 嵌套對象的處理

3. 數組的特殊處理

四、結合依賴收集的完整流程

五、數據劫持的局限性

六、Vue3 的改進方案

總結


一、什么是數據劫持?

數據劫持指的是攔截對象屬性的訪問和修改操作的能力。Vue2 通過 JavaScript 的?Object.defineProperty?API 實現這一機制,在屬性被讀取或修改時執行自定義邏輯。

二、核心 API:Object.defineProperty

Object.defineProperty?允許我們精確控制對象屬性的行為:

let obj = { name: 'Vue' };
let value = obj.name;Object.defineProperty(obj, 'name', {get() {console.log('讀取 name 屬性');return value;},set(newVal) {console.log('設置 name 屬性', newVal);value = newVal;}
});obj.name; // 控制臺輸出: "讀取 name 屬性"
obj.name = 'React'; // 控制臺輸出: "設置 name 屬性 React"

?

三、Vue2 中的數據劫持實現

1. 對象屬性的劫持

Vue 在初始化時會遍歷?data?中的所有屬性:

function defineReactive(obj, key) {let value = obj[key];Object.defineProperty(obj, key, {get() {console.log(`讀取 ${key}`);return value;},set(newVal) {console.log(`更新 ${key}`, newVal);value = newVal;// 這里會觸發視圖更新}});
}const data = { message: 'Hello Vue' };
defineReactive(data, 'message');

?

2. 嵌套對象的處理

Vue 遞歸劫持嵌套對象:

function observe(data) {if (typeof data !== 'object' || data === null) return;new Observer(data);
}class Observer {constructor(value) {this.value = value;this.walk();}walk() {Object.keys(this.value).forEach(key => {defineReactive(this.value, key);});}
}function defineReactive(obj, key) {let value = obj[key];observe(value); // 遞歸劫持子屬性Object.defineProperty(obj, key, {// getter/setter 略});
}
3. 數組的特殊處理

由于?Object.defineProperty?無法檢測數組索引變化,Vue 重寫了數組方法:

const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(method => {const original = arrayProto[method];arrayMethods[method] = function(...args) {console.log(`數組執行 ${method} 操作`);const result = original.apply(this, args);// 獲取新增的元素let inserted;switch(method) {case 'push':case 'unshift':inserted = args;break;case 'splice':inserted = args.slice(2);break;}// 劫持新增元素if (inserted) observeArray(inserted);// 觸發視圖更新return result;};
});function observeArray(items) {for (let item of items) {observe(item);}
}

?

四、結合依賴收集的完整流程

  1. 初始化階段

    • 遍歷?data?屬性,通過?defineProperty?設置 getter/setter

    • 遞歸處理嵌套對象和數組

  2. 依賴收集

    get() {if (Dep.target) { // 當前正在計算的 Watcherdep.depend();   // 將 Watcher 添加到依賴列表}return value;
    }

    3.派發更新

    set(newVal) {value = newVal;dep.notify(); // 通知所有 Watcher 更新
    }

五、數據劫持的局限性

  1. 無法檢測屬性添加/刪除

    this.obj.newProperty = 'value' // 非響應式

? ? 2. 數組索引和長度修改

this.arr[0] = 'new' // 無法檢測
this.arr.length = 10 // 無法檢測

? ?3.解決方案

this.$set(this.obj, 'newProperty', 'value')
this.$delete(this.obj, 'oldProperty')

六、Vue3 的改進方案

Vue3 使用?Proxy?替代?Object.defineProperty

  • 可直接監聽整個對象而非屬性

  • 支持動態添加屬性

  • 完美監聽數組變化

  • 性能更優

    const proxy = new Proxy(obj, {get(target, key) {// 攔截讀取操作},set(target, key, value) {// 攔截設置操作}
    });

總結

Vue2 的數據劫持機制通過?Object.defineProperty?實現,結合依賴收集派發更新,構建了響應式系統的核心。雖然存在一些局限性,但理解其原理有助于我們:

  1. 更好地使用 Vue 的響應式功能

  2. 避免常見的響應式陷阱

  3. 深入理解 Vue 的設計思想

掌握這些原理,能讓你在 Vue 開發中更加得心應手,寫出更高效、可維護的代碼!?

?

?

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

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

相關文章

數據湖 vs 數據倉庫:數據界的“自來水廠”與“瓶裝水廠”?

數據湖 vs 數據倉庫:數據界的“自來水廠”與“瓶裝水廠”? 說起“數據湖”和“數據倉庫”,很多剛入行的朋友都會覺得: “聽起來好高大上啊!但到底有啥區別啊?是湖更大還是倉庫更高端?” 我得說…

Node.js-path模塊

Path 模塊 path 模塊提供了 操作路徑 的功能,我們將介紹如下幾個較為常用的幾個 API ??path.resolve([…paths]) 將路徑片段??解析為絕對路徑??(從右向左拼接,遇到絕對路徑停止) // 若參數為空,返回當前工作目…

Java面試題029:一文深入了解MySQL(1)

歡迎大家關注我的專欄,該專欄會持續更新,從原理角度覆蓋Java知識體系的方方面面。 一文吃透JAVA知識體系(面試題)https://blog.csdn.net/wuxinyan123/category_7521898.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=7521898&

vue3.0所采用得Composition Api與Vue2.XOtions Api有什么不同?

Vue 3.0 引入的 Composition API 相較于 Vue 2.x 的 Options API 有顯著的不同。下面從幾個方面對比這兩者的差異: ? 1. 代碼組織方式不同 Vue 2.x — Options API 使用 data、methods、computed、watch 等分散的選項組織邏輯。 每個功能點分散在不同的選項中&am…

【IP 潮玩行業深度研究與學習】

潮玩行業發展趨勢分析:全球市場格局與中國政策支持體系 潮玩產業正經歷從"小眾收藏"到"大眾情緒消費"的深刻轉型,2025年中國潮玩市場規模已達727億元,預計2026年將突破1100億元,年復合增長率高達26%。這一千…

進程通信-消息隊列

消息隊列允許一個進程將一個消息發送到一個隊列中,另一個進程從該隊列中接收這個消息。 使用流程: 寫端: 使用結構體 mq_attr 設置消息隊列屬性,有四個選項: long mq_flags; // 隊列屬性: 0 表示阻塞 long …

串行通信接口USART,printf重定向數據發送,輪詢和中斷實現串口數據接收

目錄 UART通信協議的介紹 實現串口數據發送 CubeMX配置 printf重定向代碼編寫 實現串口數據接收 輪詢方式實現串口數據接收 接收單個字符 接收不定長字符串(接收的字符串以\n結尾) 中斷方式實現串口數據接收 CubeMX配置 UART中斷方式接收數據…

Kafka 生產者和消費者高級用法

Kafka 生產者和消費者高級用法 1 生產者的事務支持 Kafka 從版本0.11開始引入了事務支持,使得生產者可以實現原子操作,確保消息的可靠性。 // 示例代碼:使用 Kafka 事務 producer.initTransactions(); try {producer.beginTransaction();pr…

k8s中crictl命令常報錯解決方法

解決使用crictl命令時報默認端點棄用的報錯 報錯核心原因 默認端點棄用: crictl 會默認嘗試多個容器運行時端點(如 dockershim.sock、containerd.sock 等),但這種 “自動探測” 方式已被 Kubernetes 棄用(官方要求手動…

回轉體水下航行器簡單運動控制的奧秘:PID 控制和水動力方程的運用

在水下航行器的控制領域中,回轉體水下航行器的運動控制是一個關鍵課題。 今天,就來深入探討一下其簡單運動控制中,PID 控制以及水動力方程的相關運用。 PID 控制的基本原理PID 控制(比例 - 積分 - 微分控制)是一種廣…

從入門到精通:npm、npx、nvm 包管理工具詳解及常用命令

目錄 1. 引言2. npm (Node Package Manager)2.1 定義與用途2.2 常見命令2.3 使用示例 3. npx (Node Package Execute)3.1 定義與用途3.2 常見命令3.3 使用示例3.4 npm 與 npx 的區別 4. nvm (Node Version Manager)4.1 定義與用途4.2 安裝 nvm4.3 常見命令4.4 使用示例 5. 工具…

es6特性-第二部分

Promise 介紹和基本使用 Promise是ES6引入的異步編程的新解決方案,主要用來解決回調地獄問題。語法上 Promise是一個構造函數,用來封裝異步操作并可以獲取其成功或失敗的結果。 Promise構造函數:new Promise() Promise.prototype.then方法 Promise.prototype.ca…

java:如何用 JDBC 連接 TDSQL 數據庫

要使用JDBC連接TDSQL數據庫&#xff08;騰訊云分布式數據庫&#xff0c;兼容MySQL協議&#xff09;&#xff0c;請按照以下步驟編寫Java程序&#xff1a; 1. 添加MySQL JDBC驅動依賴 在項目的pom.xml中添加依賴&#xff08;Maven項目&#xff09;&#xff1a; <dependenc…

2025年四川省高考志愿填報深度分析與專業導向策略報告——基于599分/24000位次考生-AI

2025年四川省高考志愿填報深度分析與專業導向策略報告——基于599分/24000位次考生 摘要 本報告旨在為預估高考成績599分、全省物理類位次在24,000名左右的2025年四川考生&#xff0c;提供一份兼具科學性、前瞻性與專業深度的志愿填報策略方案。報告嚴格遵循“位次法”為核心…

spring boot項目整合百度翻譯

本片文章教大家怎樣在spring boot項目中引入百度翻譯&#xff0c;并且優雅的使用百度翻譯。 首先&#xff0c;我們要了解為什么要使用翻譯插件。為了支持多語言的國際化&#xff1b; 目前市面上最常見的后端國際化就是在resource資源目錄下設置多個語言文檔&#xff0c;這些文…

凌晨2點自動備份mysql 數據庫,mysql_backup.sh

1、編寫備份腳本&#xff1a;vim mysql_backup.sh #!/bin/bash DATE$(date %Y%m%d_%H%M%S) BACKUP_DIR"/data/mysql/backup" USER"backup_user" PASSWORD"backup**"# 邏輯備份所有數據庫 mysqldump -u$USER -p$PASSWORD eblp | gzip > $BA…

Linux系統之Tomcat服務

目錄 一、Tomcat概述 1、Tomcat介紹 2、Tomcat歷史 二、Tomcat原理分析 1、Http工作原理 2、Tomcat整體架構 3、Coyote連接器架構 4、Catalina容器架構 5、Jasper處理流程 6、JSP編譯過程 7、Tomcat啟動流程 8、Tomcat請求處理流程 三、Tomcat安裝與配置 1、單實…

FPGA芯片的供電

FPGA芯片的供電 文章目錄 FPGA芯片的供電1. 外部端口供電機制2. 內部邏輯供電機制3. 專有電路供電機制4. 電源穩定性討論總結 1. 外部端口供電機制 FPGA是專門用于數字系統設計的芯片&#xff0c;能夠正確、可靠、高效地和外界其他數字電路進行通信是FPGA芯片必備的一個功能。…

構建可無限擴展的系統:基于 FreeMarker + 存儲過程 + Spring Boot 的元數據驅動架構設計

在構建面向多行業、多客戶的大型業務系統時&#xff0c;系統的靈活性與擴展能力成為架構設計的核心目標。傳統硬編碼的開發方式在面對高頻變化、復雜組合查詢、多租戶自定義字段時&#xff0c;往往難以適應。 為了解決上述問題&#xff0c;我們提出一種 以 FreeMarker 腳本托管…

2-深度學習挖短線股-3-訓練數據計算

2-3 合并輸入特征 首先定義了數據預處理函數&#xff0c;將連續 n 天的 K 線數據&#xff08;如開盤價、收盤價、成交量等&#xff09;合并為一行特征&#xff0c;同時保留對應的目標標簽&#xff08;buy 列&#xff0c;表示是否應該買入&#xff09;&#xff1b;然后讀取股票代…