深入浅出vue.js--------(3)vm.$set和vm.$delete

$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不能侦测临时添加的属性不能侦测的限制

 

步骤:

  1. 如果是数组,使用splice添加,因为splice是经过处理的方法,会将自动将其转化为响应式

  2. 增加的target不能是vue的实例或者是根数据

  3. 增加的如果是已经存在于target上的,直接赋值

  4. 增加的,如果target不是响应式的,也直接赋值

  5. 除去以上,增加的应该设置为响应式,利用defineReactive完成响应式

 

 

$delete使用:

vm.$delete方法也是为了解决变化侦测过程中的缺陷。js没有办法侦测到一个属性在object中被删除,如果使用delete来删除一个属性,vue.js并能够侦测到并做处理。所以为了能够实现这个效果。就是删除属性后想依赖发送消息,通知watcher变化

vm.$delete(target , key)

target : {object | array}

key: {number | string}

 

  1. 和vm.$set一样,数组还是向set差不多,处理都是挺简单的

  2. 如果是vue实例或根数据,抛出异常

  3. 如果删除的key值不是target所拥有的的,不通知更新

  4. 如果删除的key值不是响应式,也不需要通知更新

  5. 真正删除,通知更新

 

具体实现代码如下:

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了。希望下次一起更。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值