派發(fā)通知發(fā)生在數(shù)據(jù)更新階段罚屋,當(dāng)數(shù)據(jù)更新時,就會觸發(fā)set函數(shù)嗅绸,我們接下來速覽set的實現(xiàn)createSetter函數(shù)
function createSetter(shallow = false) {
return function set(
target: object,
key: string | symbol,
value: unknown,
receiver: object
): boolean {
// 條件1
let oldValue = (target as any)[key]
if (isReadonly(oldValue) && isRef(oldValue) && !isRef(value)) {
return false
}
// 條件2
if (!shallow) {
if (!isShallow(value) && !isReadonly(value)) {
oldValue = toRaw(oldValue)
value = toRaw(value)
}
if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
oldValue.value = value
return true
}
} else {
// in shallow mode, objects are set as-is regardless of reactive or not
}
const hadKey =
isArray(target) && isIntegerKey(key)
? Number(key) < target.length
: hasOwn(target, key)
const result = Reflect.set(target, key, value, receiver)
// don't trigger if target is something up in the prototype chain of original
// 條件3
if (target === toRaw(receiver)) {
if (!hadKey) {
trigger(target, TriggerOpTypes.ADD, key, value)
} else if (hasChanged(value, oldValue)) {
trigger(target, TriggerOpTypes.SET, key, value, oldValue)
}
}
return result
}
}
1.如果屬性舊值是只讀的ref值脾猛,且key要賦值的不是ref類型,則函數(shù)返回false鱼鸠,不能進行值的設(shè)置
示例如下:
import { ref, reactive, readonly } from 'vue';
const num = ref(1)
const readonlObj = readonly(num)
const obj = reactive({ key: readonlObj })
obj.key = 2 // TypeError: 'set' on proxy: trap returned falsish for property 'key'
console.log(obj)
2.shallow為false的前提下猛拴,如果當(dāng)前對象不是數(shù)組,屬性舊值是ref蚀狰,且新值不是ref愉昆,則直接把新值賦值到舊值value上
示例如下:
import { ref, reactive } from 'vue';
const num = ref(1)
const obj = reactive({ key: num })
obj.key = 2
console.log(obj) // {key: Ref<2>}
3.如果屬性是當(dāng)前對象的屬性,才觸發(fā)派發(fā)操作麻蹋,如果是原型鏈上對象的屬性跛溉,則不觸發(fā)派發(fā)操作。這比較好理解扮授,如果不做限制芳室,那么原型鏈上某個屬性發(fā)生變化,那么所有實例都會受到影響刹勃,這不符合實際
現(xiàn)在知道是怎么派發(fā)了堪侯,那觸發(fā)函數(shù)長哪樣?下文我們再繼續(xù)分析荔仁!
本人菜雞伍宦,有問題望前輩及時指出芽死,不勝感激!雹拄!