您好,登錄后才能下訂單哦!
這篇文章主要講解了“Vue的$set怎么實現”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Vue的$set怎么實現”吧!
let dataArr = ["item1"];
let dataObject = {
name: "ccs"
};
dataArr[2] = "item2";
dataObject.age = 22;
響應失敗,頁面沒有顯示更新新增的數據
this.$set(this.dataArr,2,'item2')
this.$set(this.dataObject,'age',22)
響應成功,頁面顯示更新新增的數據
接下來我們看一下$set在Vue中的定義
function set(target: Array<any> | Object, key: any, val: any): any {
if (
process.env.NODE_ENV !== "production" &&
(isUndef(target) || isPrimitive(target))
) {
warn(
`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`
);
}
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key);
target.splice(key, 1, val);
return val;
}
if (key in target && !(key in Object.prototype)) {
target[key] = val;
return val;
}
const ob = (target: any).__ob__;
if (target._isVue || (ob && ob.vmCount)) {
process.env.NODE_ENV !== "production" &&
warn(
"Avoid adding reactive properties to a Vue instance or its root $data " +
"at runtime - declare it upfront in the data option."
);
return val;
}
if (!ob) {
target[key] = val;
return val;
}
defineReactive(ob.value, key, val);
ob.dep.notify();
return val;
}
在源碼中首先判斷set的目標是否是undefined
和基本類型
如果是undefined
或基本類型
就報錯,
因為用戶不應該往undefined和基本類型中set東西,
然后又判斷了目標是否是數組與key是不是合法的index,合法的index是指值為大于等于0的整數,
如果兩個條件都成立就對目標數組調用splice方法插入或者修改數組
,
這里的splice
不是普通的splice
,是王維詩里的splice,是被vue代理重寫過的splice
$set實現數組修改響應的方式是代理重寫的數組的一部分方法,接下來我們看一下具體實現
const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
function def(obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true
});
}
methodsToPatch.forEach(function (method) {
const original = arrayProto[method]
def(arrayMethods, method, function mutator (...args) {
const result = original.apply(this, args)
const ob = this.__ob__
let inserted
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if (inserted) ob.observeArray(inserted)
ob.dep.notify()
return result
})
})
vue中代理重寫的不只是splice
,有push、pop、shift、unshift、splice、sort、reverse
這七個方法,
首先執行了const result = original.apply(this, args)
執行原本數組的方法并獲取它的值,接下來判斷如果是往數組中添加值就將新添加的值也實現響應式
,
最后一步拿到這個數組的_ob_對象
對_ob_
里的dep進行派發更新。
想深入了解vue的響應式可以查閱往期文章
面試官問你Vue2的響應式原理,你怎么答? - 掘金 (juejin.cn)
$set
中下半部分的邏輯就是用來處理對象響應的,我們接著往下看
if (key in target && !(key in Object.prototype)) {
target[key] = val;
return val;
}
const ob = (target: any).__ob__;
if (!ob) {
target[key] = val;
return val;
}
defineReactive(ob.value, key, val);
ob.dep.notify();
return val;
首先判斷了屬性如果在目標對象中直接return結束邏輯,
因為vue只有添加目標對象中原本沒有的屬性時才會失去響應,例如 let obj={} obj.name='ccs'
,
vue在初始化的時候會將data里的所有屬性都變成響應式,如果的值是對象或者數組則會new一個Observer
實例儲存在__ob__,想深入了解vue的響應式可以查閱往期文章
面試官問你Vue2的響應式原理,你怎么答? - 掘金 (juejin.cn)
拿到這個對象的_ob_進行判斷,如果不存在就說明是未經過vue初始化的普通對象而不是響應式對象否則就手動通過defineReactive
為屬性添加get方法與set方法實現響應,
然后手動調用dep
里的notify()
發布更新。
感謝各位的閱讀,以上就是“Vue的$set怎么實現”的內容了,經過本文的學習后,相信大家對Vue的$set怎么實現這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。