$set和$delete
作为vue的使用者来说,set并不陌生,set的使用场景是,当属性没有在data函数中定义的时候,则这个属性并不是响应式,而this.$set则能将这个属性设置为响应式。
$set使用语法
vm.$set(target , key , value)
参数:
target:{object | array}
key: {string | number}
value: { any }
返回值:unwatch函数
作用:在object撒花姑娘设置一个属性,如果object是响应式的,vue.js会保证属性被创建后也是响应式,并且触发视图更新。这个方法主要用来避开vue不能侦测临时添加的属性不能侦测的限制
步骤:
-
如果是数组,使用splice添加,因为splice是经过处理的方法,会将自动将其转化为响应式
-
增加的target不能是vue的实例或者是根数据
-
增加的如果是已经存在于target上的,直接赋值
-
增加的,如果target不是响应式的,也直接赋值
-
除去以上,增加的应该设置为响应式,利用defineReactive完成响应式
$delete使用:
vm.$delete方法也是为了解决变化侦测过程中的缺陷。js没有办法侦测到一个属性在object中被删除,如果使用delete来删除一个属性,vue.js并能够侦测到并做处理。所以为了能够实现这个效果。就是删除属性后想依赖发送消息,通知watcher变化
vm.$delete(target , key)
target : {object | array}
key: {number | string}
-
和vm.$set一样,数组还是向set差不多,处理都是挺简单的
-
如果是vue实例或根数据,抛出异常
-
如果删除的key值不是target所拥有的的,不通知更新
-
如果删除的key值不是响应式,也不需要通知更新
-
真正删除,通知更新
具体实现代码如下:
import Vue from 'vue'
Vue.prototype.$set = newSet
Vue.prototype.$delete = newDelete
function isValidArray (value) {
}
function newSet (target, key, value) {
const ob = target.__ob__
// 是数组
if (Array.isArray(target) && isValidArray(target)) {
target.length = Math.max(key, target.length)
target.splice(key, 1, value)
return value
}
// 如果已经在target中
if (key in target && !(key instanceof Object.prototype)) {
target[key] = value
return value
}
// 如果不是vue实例或者是根数据
if (target._isVue || (ob && ob.vmCount)) {
process.env.NODE_ENV !== 'production' && warning(`Aviod adding properties to a vue instance or its root $data...`)
return value
}
// 本来target就不是响应式的数据
if (!ob) {
target[key] = value
return value
}
// 最后要完成响应式的
defineReactive(target, key, value)
ob.dep.notify()
return value
}
function newDelete (target, key) {
const ob = target.__ob__
if (Array.isArray(target) && isValidArray(target)) {
target.splice(key, 1)
return
}
if (target._isVue && (ob && ob.vmCount)) {
process.env.NODE_ENV !== 'production' && warning(`Aviod delete properties on a vue instance or its root $data...`)
return
}
if (!hasOwn(target, key)) {
return
}
delete target[key];
// r如果不是响应式就不需要通知了
if (!ob) {
return
}
ob.dep.notify()
}
isVue
来判断是不是vue实例,vm.vmCount
来判断是不是数据对象
好久没发了,关于$watch看完了还没整理,最近又开始学ts了。希望下次一起更。