(1)vm.$delete的作用是删除数据中个某个属性。
(2)由于Vue.js的变化侦测是使用Object.defineProperty实现的,所以如果数据使用delete关键字删除的,那么无法发现数据发生了变化。
(3)为了解决这个问题,Vue.js提供了vm.$delete方法来删除数据种的某个属性,并且此时Vue.js可以侦测到数据发生了变化。
vm.$delete(target,key)
(1)参数
注意:仅在2.2.0+版本中支持Array+index的用法。
(2)用法
1、删除对象的属性。
2、如果对象是响应式的,需要确保删除能触发更新视图。
3、这个方法主要用于避开Vue.js不能检测到属性被删除的限制。
4、在2.2.0+中,同样支持在数组上工作。
(3)注意
目标对象不能是Vue.js实例或Vue.js实例的根数据对象。
(1)vm.$delete方法也是为了解决变化侦测的缺陷。在ES6之前,Javascript并没有办法侦测到一个属性在object中被删除,所以如果使用delete来删除一个数据,Vue.js根本不知道这个属性被删除了。
(2)使用vm.$delete能帮助我们在删除属性后自动向依赖发送消息,通知Watcher数据发生了变化。
(3)原理:删除属性后向依赖发消息。
import {del} from '../observer/index'
Vue.prototype.$delete = del;
在Vue.js的原型上挂载$delete方法。
(4)del函数
export function del(target,key){
const _ob_ = target._ob_;
delete target[key];
_ob_.dep.notify();
}
先从target中将属性key删除,然后向依赖发送消息。
(5)处理数组的情况
export function del(target,key){
//新增
if(Array.isArray(target)&&isValidArrayIndex(key)){
target.splice(key,1)
return;
}
const _ob_ = target._ob_;
delete target[key];
_ob_.dep.notify();
}
因为使用了splice方法,数组拦截器会自动向依赖发送通知。
(6)与 vm.$set一样,vm.$delete也不可以在Vue.js实例或Vue.js实例的跟数据对象上使用。
export function del(target,key){
if(Array.isArray(target)&&isValidArrayIndex(key)){
target.splice(key,1)
return;
}
const _ob_ = target._ob_;
//新增
if(target._isVue || (ob && ob.vmCount)){
process.env.NODE_ENV !== 'production' && warn(
'Avoid deleting properties on a Vue instance or its root $data' +
'- just set it to null'
)
retun val;
}
delete target[key];
_ob_.dep.notify();
}
1、如果target上有_isVue属性(target是Vue.js实例)或则ob.vmCount数量大于1(target是根数据),则直接返回,终止程序继续执行,并且如果是开发环境,会在控制台中发出警告。
(6)如果删除的这个key不是target自身的属性,就什么都不做,直接退出程序执行。
export function del(target,key){
if(Array.isArray(target)&&isValidArrayIndex(key)){
target.splice(key,1)
return;
}
const _ob_ = target._ob_;
if(target._isVue || (ob && ob.vmCount)){
process.env.NODE_ENV !== 'production' && warn(
'Avoid deleting properties on a Vue instance or its root $data' +
'- just set it to null'
)
retun val;
}
//如果key不是target自身的属性,则终止程序继续执行
if(!hasOwn(target,key)){
return;
}
delete target[key];
_ob_.dep.notify();
}
(7)判断target是不是一个响应式数据,也就是说要判断target身上存不存在_ob_属性。只有响应式数据才需要发送通知,非响应式数据只需要执行删除操作即可。
export function del(target,key){
if(Array.isArray(target)&&isValidArrayIndex(key)){
target.splice(key,1)
return;
}
const _ob_ = target._ob_;
if(target._isVue || (ob && ob.vmCount)){
process.env.NODE_ENV !== 'production' && warn(
'Avoid deleting properties on a Vue instance or its root $data' +
'- just set it to null'
)
retun val;
}
//如果key不是target自身的属性,则终止程序继续执行
if(!hasOwn(target,key)){
return;
}
delete target[key];
//如果ob不存在,则直接终止程序
if(!_ob_){
return;
}
_ob_.dep.notify();
}
如果数据不是响应式的,则使用return语句阻止执行发送通知语句。