Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

响应式之defineReactive - 6 #6

Open
any-u opened this issue Mar 3, 2021 · 0 comments
Open

响应式之defineReactive - 6 #6

any-u opened this issue Mar 3, 2021 · 0 comments

Comments

@any-u
Copy link
Owner

any-u commented Mar 3, 2021

响应式之defineReactive - 6

export function defineReactive (
  obj: Object,
  key: string,
  val: any,
  customSetter?: ?Function,
  shallow?: boolean
) {
  // 新建 dep 实例
  const dep = new Dep()
	
  // 获取 obj 自身属性,而非原型链上的
  // 属性如果不可配置,则返回
  const property = Object.getOwnPropertyDescriptor(obj, key)
  if (property && property.configurable === false) {
    return
  }

  // 缓存 getter 与 setter
  // 防止后续通过 Object.defineProperty 时被重写
  const getter = property && property.get
  const setter = property && property.set
  // 补充: val存在(shallow 为 false),则会深度监听 --> 下文childOb
  // !getter --> 当属性存在 get,初始化的时候不做触发,当真正需要值的时候,再触发 getter 获取
  // setter -> 如果属性不存在 set, 则触发深度监听val(即 val=obj[key]),
  //           那开始不深度监听,下文会创建 get,从而又变成深度监听, 这造成了定义响应式数据时行为的不一致
  if ((!getter || setter) && arguments.length === 2) {
    val = obj[key]
  }
	
  // shallow 为 false 时监听 val(对象的值),即深度监听
  let childOb = !shallow && observe(val)
  // Object.defineProperty 定义 get 与 set
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      // 触发缓存的 getter 获取值
      const value = getter ? getter.call(obj) : val
      // Dep.target 存在的时候
      if (Dep.target) {
        // dep收集依赖
        dep.depend()
        // 如果子类观察者存在
        if (childOb) {
          // 子类依赖收集
          childOb.dep.depend()
          // 如果是数组,遍历每个元素来收集依赖
          if (Array.isArray(value)) {
            dependArray(value)
          }
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      const value = getter ? getter.call(obj) : val
			
      // 后一部分指代 NaN -> 值与自身都不全等的, 新旧值都是 NaN, 直接 return
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      // #7981: 用于不带 setter 的访问器属性
      // 当 property 为 undefined 时,getter 和 setter 是 undefined
      // 这样可以保证程序正常执行
      if (getter && !setter) return
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      // 设置 newVal 后重新深度监听新值
      childOb = !shallow && observe(newVal)
      // 通知依赖更新
      dep.notify()
    }
  })
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant