官方api解釋了它的使用場景
向響應式對象中添加一個屬性,並確保這個新屬性同樣是響應式的,且觸發視圖更新。它必須用於向響應式對象上添加新屬性,因爲 Vue 無法探測普通的新增屬性 (比如 this.myObject.newProperty = ‘hi’)
所以我們要知道,只有先定義在data 裏 數據才具有響應式,如果自己後添加的屬性是不具備響應式的
比如下邊這個 屬性a 具有響應式,但是b 就不會,如果你想讓這個b 具有響應式
你可以使用 Vue.set(this.model, “b”, 20 ) 這樣寫使他具有響應式,
還有就是修改數組的某個值, 你直接通過索引的這種方式修改是不可以的,
但是你如果使用數組的 增刪改查,排序,反轉
方法 是會觸發視圖更新的,因爲Vue內部重寫了這些方法,並定義了響應式
new Vue({
data(){
return {
list: [1, 2, 3, 4]
model:{
a: 10
}
}
}
})
mounted(){
this.list[0] = 5;
this.model.b = 20;
}
那麼, 接着來看看 set 方法是怎麼做的
src/core/observer/index.js
export 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)}`)
}
/**
* 這裏判斷你傳入是數組,並且key 滿足是數組的索引
*/
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key)
target.splice(key, 1, val)
return val
}
/**
* 這裏判斷你傳入的是個對象,那就直接賦值操作,最後再調用
* defineReactive(ob.value, key, 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)
// 調用 notify()方法,通知更新
ob.dep.notify()
return val
}
src/core/shared/util.js
isValidArrayIndex()就是判斷是否滿足是索引
/**
* Check if val is a valid array index.
*/
export function isValidArrayIndex (val: any): boolean {
const n = parseFloat(String(val))
return n >= 0 && Math.floor(n) === n && isFinite(val)
}
這段代碼可以看出來,調用這個方法,傳入3個參數(target, key ,val),返回值就是最後傳入的 val
這個方法內部做了3件事(原理也比較好理解):
- 判斷是數組的情況 並且滿足是數組的索引, 最後通過
splice()
方法來處理是增加一條數據還是 修改某個索引的數據(所以你如果不想用set,直接使用這個方法也是可以修改數組的數據的,並且具有響應式)- 判斷是對象的情況, 直接通過
target[key] = val
來添加屬性或者修改屬性對應的值, 接着再調用 defineReactive(ob.value, key, val),給新添加的屬性再重新定義響應式- 最後調用 notify() 方法觸發更新操作