• 实现一个最小版本vue(二)之observer


    observer

    功能

    • 负责把data选项中的属性转换成响应式数据

    • data中的某个属性也是对象,把该属性转换成响应式数据。

    • 数据变化发出通知

    • 结构

    实现思路

    1. walk方法判断传入的data是否是对象,加强代码健壮性
    2. 遍历data对象所有属性,调用defineReactive,转化为响应式数据
    3. defineReactive需要传3个参数,第三个参数直接把val传入,而不是通过obj[key]获取,是因为,访问实例属性时,首先触发vue.js里的get方法,这个get调用了data[key],这里会触发observer里的get方法,如果在observer里的get里直接使用obj[key],则又触发了这个get方法,产生一个死递归,会发生堆栈溢出错误
    4. 这第三个参数val是局部对象,执行完成应该被释放,这里没有被释放,原因是:传入的objdata对象($data),而$data引用了get方法,外部引用了这个方法,而get 又用到了val,所以不会释放掉,产生了闭包
    5. 如果data对象里还包含对象,需要在defineReactive开始时也调用一次walk,判断内部是否还有嵌套,把嵌套对象也转换成响应式
    6. 修改data中的值,修改后的值也需要是响应式的,所以在set方法里,也调用一次walk

    代码

    class Observer {
      constructor (data) {
        this.walk(data)
      }
    
      walk (data) {
        // 1.判断data是否时对象
        if (!data || typeof data !== 'object') {
          return
        }
        // 2.遍历data对象所有属性
        Object.keys(data).forEach(key => {
          this.defineReactive(data, key, data[key])
        })
      }
    
      // 定义响应式数据
      defineReactive (obj, key, val) {
        // 如果val此时是对象,会把val内部的属性转换成响应式的
        this.walk(val)
        const that = this
        let dep = new Dep()
        Object.defineProperty(obj, key, {
          enumerable: true,
          configurable: true,
          get () {
            // 收集依赖
            Dep.target && dep.addSub(Dep.target)
            // 如果使用obj[key],则又触发了get方法,死递归,会发生堆栈溢出错误
            // return obj[key]
            return val
          },
          set (newValue) {
            if (newValue === val) {
              return
            }
            val = newValue
            // 新值也要通过walk进行响应式转换
            that.walk(newValue)
            // 发送通知
            dep.notify()
          },
        })
      }
    }
    
  • 相关阅读:
    go chapter 4
    go chapter 3
    ETCD相关介绍--整体概念及原理方面
    go chapter 2
    go chapter 1
    使用kubeadm搭建kubernetes1.10集群 Posted on April 14, 2018
    单用户passwd修改root密码没反应
    is not in the sudoers file解决方案
    版本更换,开始学习鸟哥的私房菜
    ubuntu 常见命令
  • 原文地址:https://www.cnblogs.com/Evo1uti0n/p/13260157.html
Copyright © 2020-2023  润新知