Vue監(jiān)視數(shù)據(jù)的原理和set()的使用方法示例
前言
在 Vue 中,Vue.set()(或 this.$set())是用于解決響應式數(shù)據(jù)更新檢測的重要方法,其底層與 Vue 的數(shù)據(jù)監(jiān)視原理緊密相關(guān)。以下從使用場景和實現(xiàn)原理兩方面詳細說明:
一、Vue.set () 的使用場景與用法
1. 為什么需要 Vue.set ()?
Vue 的響應式系統(tǒng)通過 Object.defineProperty(Vue 2)或 Proxy(Vue 3)實現(xiàn)數(shù)據(jù)監(jiān)聽,但存在限制:
- 無法檢測對象新增的屬性或刪除的屬性;
- 無法檢測數(shù)組通過索引修改元素或修改數(shù)組長度的操作。
此時,直接修改數(shù)據(jù)不會觸發(fā)視圖更新,需要用 Vue.set() 強制觸發(fā)響應式更新。
2. 用法
- 語法:
// 全局方法 Vue.set(target, propertyName/index, value) // 實例方法(組件內(nèi)) this.$set(target, propertyName/index, value)
- 參數(shù):
target:需要修改的響應式對象或數(shù)組(必須是已被 Vue 響應式系統(tǒng)劫持的對象);propertyName/index:新增 / 修改的屬性名(對象)或索引(數(shù)組);value:對應的值。
3. 典型場景
給對象新增響應式屬性:
data() { return { user: { name: '張三' } } }, methods: { addAge() { // 直接新增屬性,視圖不會更新 this.user.age = 20; // 無效 // 使用 $set,視圖會更新 this.$set(this.user, 'age', 20); // 有效 } }修改數(shù)組的指定元素:
data() { return { list: ['蘋果', '香蕉'] } }, methods: { updateItem() { // 直接通過索引修改,視圖不會更新 this.list[1] = '橙子'; // 無效 // 使用 $set,視圖會更新 this.$set(this.list, 1, '橙子'); // 有效 } }
二、Vue 監(jiān)視數(shù)據(jù)的原理
Vue 實現(xiàn)數(shù)據(jù)響應式的核心是對數(shù)據(jù)進行劫持,并在數(shù)據(jù)變化時通知依賴更新視圖。不同 Vue 版本的實現(xiàn)方式略有差異:
1. Vue 2 的響應式原理(Object.defineProperty)
初始化劫持:
當組件初始化時,Vue 會遍歷data中的所有屬性,通過Object.defineProperty為每個屬性添加getter和setter:getter:當屬性被訪問時觸發(fā),用于收集依賴(記錄哪些視圖 / 計算屬性依賴該數(shù)據(jù))。setter:當屬性被修改時觸發(fā),用于通知依賴更新(觸發(fā)視圖重新渲染)。
局限性:
- 只能劫持初始化時已存在的屬性,新增屬性默認沒有
getter/setter,因此無法被監(jiān)測。 - 數(shù)組的
length修改和索引賦值不會觸發(fā)setter(Vue 對數(shù)組的 7 個方法進行了重寫,如push、splice等,這些方法會觸發(fā)更新,但直接修改索引 / 長度不會)。
- 只能劫持初始化時已存在的屬性,新增屬性默認沒有
2. Vue 3 的響應式原理(Proxy)
初始化劫持:
Vue 3 使用 ES6 的Proxy對data對象進行代理,生成一個代理對象(Proxy)。Proxy可以攔截對象的所有操作(包括新增屬性、刪除屬性、索引訪問等),從而解決了 Vue 2 的局限性。優(yōu)勢:
- 能監(jiān)測新增屬性(
proxy.xxx = value會被set攔截); - 能監(jiān)測刪除屬性(
delete proxy.xxx會被deleteProperty攔截); - 能監(jiān)測數(shù)組索引修改和長度變化(通過
set攔截)。
- 能監(jiān)測新增屬性(
三、Vue.set () 的底層實現(xiàn)邏輯
Vue.set() 的核心作用是手動為數(shù)據(jù)添加響應式能力,并觸發(fā)更新:
對于對象:
- 檢查目標對象是否為響應式對象(是否有
__ob__標識,Vue 內(nèi)部用于標記響應式對象)。 - 若屬性已存在,則直接修改值并觸發(fā)
setter。 - 若屬性不存在,則通過
Object.defineProperty(Vue 2)或Proxy的set攔截(Vue 3)為新屬性添加響應式,并手動觸發(fā)依賴更新。
- 檢查目標對象是否為響應式對象(是否有
對于數(shù)組:
- 調(diào)用數(shù)組的
splice方法(Vue 已重寫該方法,會觸發(fā)更新),通過splice(index, 1, value)實現(xiàn)元素修改,從而觸發(fā)視圖更新。
- 調(diào)用數(shù)組的
總結(jié)
- Vue.set () 的作用:解決 Vue 響應式系統(tǒng)無法檢測 “對象新增屬性”“數(shù)組索引修改” 等操作的問題,強制為數(shù)據(jù)添加響應式并觸發(fā)視圖更新。
- 監(jiān)視數(shù)據(jù)的原理:
- Vue 2 基于
Object.defineProperty劫持屬性的getter/setter,實現(xiàn)依賴收集和更新通知。 - Vue 3 基于
Proxy代理整個對象,攔截所有操作,天然支持更多場景的監(jiān)測。
- Vue 2 基于
理解這一機制有助于避免 “數(shù)據(jù)修改后視圖不更新” 的常見問題,也能更深入地掌握 Vue 響應式系統(tǒng)的設計思想。
到此這篇關(guān)于Vue監(jiān)視數(shù)據(jù)的原理和set()使用方法的文章就介紹到這了,更多相關(guān)Vue監(jiān)視數(shù)據(jù)和set()使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3封裝AES(CryptoJS)前端加密解密通信代碼實現(xiàn)
防止數(shù)據(jù)被爬取,前后端傳參接收參數(shù)需要加密處理,使用AES加密,這篇文章主要給大家介紹了關(guān)于vue3封裝AES(CryptoJS)前端加密解密通信代碼實現(xiàn)的相關(guān)資料,需要的朋友可以參考下2023-12-12
關(guān)于ElementUI el-table 鼠標滾動失靈的問題及解決辦法
這篇文章主要介紹了關(guān)于ElementUI el-table 鼠標滾動失靈的問題及解決辦法,本文給大家分享問題所在原因及解決方案,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08
動態(tài)實現(xiàn)element ui的el-table某列數(shù)據(jù)不同樣式的示例
這篇文章主要介紹了動態(tài)實現(xiàn)element ui的el-table某列數(shù)據(jù)不同樣式的示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01

