这一次,彻底搞懂双向数据绑定04

这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战

一、实现数据从data到view的单向数据绑定

  1. 当data发生变化的时候首先触发数据劫持的setter函数
  set(newVal) {
    value = newVal
    Observe(value)
    // 通知每个订阅者更新自己的文本
    dep.notify()
  }
复制代码

setter函数先改变新的值,然后通知每一个订阅者。

  1. Dep类的notify函数通知每一个订阅者watcher
  notify() {
    this.subs.forEach(watcher => watcher.update())
  }
复制代码
  1. Watcher类的update函数获取最新的值并调用渲染函数。
  update() {
    const value = this.key.split('.').reduce((newObj,k) => newObj[k],this.vm)
    this.cb(value);
  }
复制代码
  1. 渲染函数执行渲染
new Watcher(vm,execResult[1],(newValue) => {
  node.textContent = text.replace(regMustache,newValue);
})
复制代码

二、实现文本框的单向数据绑定

在渲染函数中首先判断当前节点是否为input并且含有属性v-model,有则获取值并创建watcher实例。

// 判断当前的节点是否为input框
if (node.nodeType === 1 && node.tagName.toUpperCase() === 'INPUT') {
  // 得到当前元素的所有属性节点
  const attrs = Array.from(node.attributes);
  const findResult = attrs.find(x => x.name === 'v-model')
  if (findResult) {
    // 获取当前v-model属性的值 v-model="name" v-model="info.a"
    const expStr = findResult.value;
    const value = expStr.split('.').reduce((newObj,k) => newObj[k],vm);
    node.value = value;
    // 创建Watcher的实例
    new Watcher(vm,expStr,(newValue) => {
      node.value = newValue;
    })
  }
}
复制代码

三、实现文本框的双向数据绑定

实现文本框的双向数据绑定重点是在单向数据绑定的基础上,监听文本框的输入事件,拿到文本框的最新值,并将最新值更新到vm上即可。

// 判断当前的节点是否为input框
if (node.nodeType === 1 && node.tagName.toUpperCase() === 'INPUT') {
  // 得到当前元素的所有属性节点
  const attrs = Array.from(node.attributes);
  const findResult = attrs.find(x => x.name === 'v-model')
  if (findResult) {
    // 获取当前v-model属性的值 v-model="name" v-model="info.a"
    const expStr = findResult.value;
    const value = expStr.split('.').reduce((newObj,k) => newObj[k],vm);
    node.value = value;
    // 创建Watcher的实例
    new Watcher(vm,expStr,(newValue) => {
      node.value = newValue;
    })

    // 监听文本框的input输入事件,拿到文本框的最新值,并把最新值更新到vm上即可
    node.addEventListener('input',e => {
      const keyArr = expStr.split('.');
      const obj = keyArr.slice(0,keyArr.length-1).reduce((newObj,k) => newObj[k],vm);
      obj[keyArr[keyArr.length - 1]] = e.target.value;
    })
  }
}
复制代码

总结

Vue的双向数据绑定是数据劫持、模板编译、发布订阅模式等综合知识点的体现,是我们必须要学会并掌握的知识点。

猜你喜欢

转载自juejin.im/post/7066208245106343967