vue源码学习:set()原理

80 阅读1分钟

前期准备 1.下载源码,本地切换分支到vue@2.6

解析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)}`)
  }
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val)
    return 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)
  ob.dep.notify()
  return val
}

官方介绍

image.png

总结

  1. 传入参数(数组/对象,键,修改属性)
  2. 判断当前target是否为数组/对象,不是发出警告 isUndef() 判断是否为null或者undefined,isPrimitive()判断是否为string,number,symbol
  3. 如果为数组,确定好数组长度,通过splice方法替换
  4. 如果是对象并且非原型属性,直接修改
  5. ob 为响应式对象,判断如果实在vue实例或者是$data上编辑属性,发出警告并返回当前值
  6. 如果非响应式属性直接赋值,返回 7.defineReactive() target是响应式对象,进行配置配置依赖
  7. ob.dep.notify()发布通知