Vue源码学习:手写Vue(二)—— Dep & Watcher

本章要实现依赖收集

0.先看看下面案例,理一下思路

    const app = new HVue({
      template: `
        <div>
          <span>{{msg1}}<span>  
          <span>{{msg2}}<span>  
          <span>{{msg3}}<span>  
        </div>
      `,
      data: {
        msg1: 'msg1',
        msg2: 'msg2',
        msg3: 'msg3'
      },
      created() {
        this.msg1 = 'new msg1'
        this.msg3 = 'new msg3'
      }
    })

msg1被修改,视图有两处要更新;
msg2被修改,视图更新;
msg3被修改,视图不更新。
如何实现呢,需要扫描视图收集依赖,知道视图中哪些地方对数据有依赖,这样当数据变化时就能触发相应视图更新了。

1、每一个属性对应一个dep,每个dep可以对应多个watcher,创建Dep 、Watcher用于依赖收集

// hvue.js
class HVue {
 
}

class Dep {
  constructor() {
    this.deps = [] // 每一属性都对应一个dep,每个dep可以对应多个watcher,所以用一个数组存储相应的watcher
  }
  addDep(dep) {
    this.deps.push(dep) 
  }
  notify() { // 通知更新视图
    this.deps.forEach(dep => dep.update())
  }
}

class Watcher {
  construcotr() {
    Dep.target = this // 每新建一个watcher实例时,会将Dep的静态属性指向新的实例
  }
  update() {
    console.log('属性更新了');
  }
}

2、每个性都对应一个dep,属性响应化时都调用defineReactive方法添加,所以在该方法里为每个属性都创建一个dep实例。

// hvue.js

class HVue {
  defineReactive(obj, key, val) {
    const dep = new Dep() // 为每个属性都创建一个dep实例
    Object.defineProperty(obj, key, {
      get() {
        Dep.target && dep.addDep(Dep.target) // 当我们创建一个weatcher实例时,如果一读某个属性时我们就把这个依赖添加到deps数组里,这样将来数据更新时,就可以通知去通知谁了
        return val;
      },
      set(newVal) {
        if (newVal !== val) {
          val = newVal
          // console.log(`${key}更新了,新值是:${val}`);
          dep.notify() // 通知更新
        }
      }
    })
    this.observe(val) // data对中的每个属性值也可能是对象,通过递归实现响应化
  }
}

现在可以测试一下代码
// hvue.js

class HVue {
  constructor(options) {
    this.$options = options
    this.$data = options.data

    this.observe(this.$data) // 实现$data响应式

    new Watcher()
    this.$data.message
    new Watcher()
    this.$data.foo.bar
  }
}

看到这日志说明代码生效了
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值