Vue双向绑定原理及实现

Vue的双向绑定原理鄙人认为就是给数据赋能------(自我检测能力)

HTML代码结构

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Vue双向绑定原理实现</title>
</head>

<body>
  <div>埋埋最可爱</div>
  <input placeholder="请输入" type="text" />
</body>
<script src="./releaseAndsub.js"></script>
<script src="./observer.js"></script>
<script>
  const inputNode = document.querySelector('input')
  const data = createData({
    name: '埋埋',
    gengder: 'female',
  })

  observer(inputNode, data)
</script>

</html>

一、怎么赋能
我们都知道,Vue的数据结构是对象键值对结构。那好,如果我们将对象内原本的键值对一一变成get/set方法,这样我们就可以在get/set方法中给数据赋予自我检测能力。OK,首先我们得知道怎么将原本的键值对改变成get/set。我们可以利用Object.defineProperty来对对象中的属性进行改造拦截,这就意味着对象中将没有实质性的key: value形式,有的只有get/set

二、创造观察者observer对model和view进行监听
目前我们只是对数据对象进行了改造,使其拥有自我变化读取监听能力,这就意味着我们观察者中数据监听的部分已经完成。OK,那观察者还需要监听View的变化,那怎么做?对于我们的实验而言,我们便是利用各种相应的事件回调函数来监听View层的的变化,比如oninput。好的,现在我们知道了model和view层的监听,我们就可以来编写我们的观察者了。

// observer.js

'use strict'

// 通知发布订阅模式改变视图
let [geted, changed] = [false, false]

// 观察者----view视图监测
function observer(changeNodes, data) {
  const changeNodesArr = changeNodes instanceof NodeList ? [...changeNodes] : [changeNodes]
  changeNodesArr.forEach(node => {
    node.oninput = function () {
      // 发布订阅者模式,更新model和视图相关操作代码
    }
  })
}

// 观察者----model数据监测
function createData(data) {
  const keyArr = Object.keys(data)
  keyArr.forEach(item => {
    changeItem(data, item, data[item])
  })
  return data
}

// 观察者----数据内部单元改造
function changeItem(data, key, value) {
  Object.defineProperty(data, key, {
    get() {
      geted = true
      return value
    },

    set(newValue) {
      value = newValue
      changed = true
    }
  })
}

三、创建发布订阅者ReleaseAndsub对model和view进行更新
目前我们有了观察者监听model和view,但是我们还缺少发布订阅者对发布者相应的发布内容(model)和订阅者的相应状态(view)进行更新。OK,具体如何更新的实现方式,人各有异,但只要理解到这个原理真正的执行过程便可,在此我记录下本人的实现方法。

'use strict'

class ReleaseAndsub {
  constructor(data, key, target, relies) {
    this.data = data
    this.key = key
    this.target = target
    this.relies = relies instanceof NodeList ? [...relies] : [relies] // 收集依赖项
  }

  // 视图改变model
  viewToChangeModel() {
    const self = this
    self.data[self.key] = self.target.value
  }

  // model改变视图(根据观察者多提供的changed依据,决定是否改变视图层)
  modelTochangeView() {
    const self = this
    self.relies.forEach(item => {
      item.innerText = self.target.value
    })
    changed = false
    geted = false
  }

}

四、整合代码
现在我们有了各个组件,我们便可以进行代码的整合了。具体代码我就不贴了,需要者可点击下方本人的gitHub仓库。

代码仓库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值