美文网首页
Object.defineProperty() 实现双向数据绑定

Object.defineProperty() 实现双向数据绑定

作者: 梦晓半夏_d68a | 来源:发表于2020-08-05 08:24 被阅读0次

  Object.defineProperty() 基础知识请看上一篇文章:理解Object.defineProperty()
  在上篇文章最后我提到了vue.js 是通过Object.defineProperty() 方法来实现双向数据绑定的,双向数据绑定原理我准备在下一篇Vue.js 双向数据绑定原理剖析
再细说,这一篇先借助一个小例子自己来实现双向数据绑定。

  那么双向数据绑定到底是什么呢?

  • 当数据发生变化的时候,使用到数据的地方同步变化,即模型到视图(model => view)
  • 当使用到数据的地方发生改变的时候,数据也同步变化,即视图到模型(view => model)

  因此监听数据及视图的变化是实现双向数据绑定的核心,那么如何监听数据的变化呢?我在理解Object.defineProperty()提到Object.defineProperty()方法里的get()set()可以分别监听数据的获取和设置。话不多说,直接上代码。

    let aVal = 1
    let obj = {}
    Object.defineProperty(obj, 'a', {
      set(newVal) {
        console.log('设置a')
        aVal = newVal
      },
      get() {
        console.log('获取a')
        return aVal
      }
    })
双向绑定.gif

代码分析:
  当获取obj.a时,get方法被调用,执行get()里的代码输出‘获取a’并返回aVal的值作为obj.a的值;当设置obj.a为100时,set方法被调用,执行set()里的代码输出'设置 a'并修改aVal的值为100,这样我们就做到了监控obj.a的存取。

  其实在set()方法里我们不止可以进行打印操作,还可以进行其他的操作,比如修改页面元素显示的值,这是不是就实现了从模型到视图的同步?

模型-->视图

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <input type="text" id="my-input" value="看我变变变">
  <h3 id="my-title">看我变变变</h3>
</head>
<body>
  <script>
    let message = ''
    let obj = {}
    Object.defineProperty(obj, 'show', {
      set(newVal) {
        console.log('设置show')
        message = newVal
        document.querySelector('#my-input').value = newVal
        document.querySelector('#my-title').innerText = newVal
      },
      get() {
        console.log('获取show')
        return message
      }
    })
  </script>
</body>
</html>
数据到视图.gif

  从上面的执行结果可以看到,已经实现了监控数据(模型)改变,视图同步跟着变化,要实现双向绑定,还需要做到监控视图改变,让数据(模型)同步变化。

视图-->模型

   以id为‘#my-input’ 的input框为例,需求是文本框输入内容一旦发生变化,同步更新obj.show的值。具体做法是:监听文本框的“ keyup” 事件。因为每当文本框的值发生改变就会触发keyup事件,那么我们只需要在keyup事件里面修改obj.show的值就好了,这就实现了视图到模型(view => model)的同步。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <input type="text" id="my-input" value="看我变变变">
  <h3 id="my-title">看我变变变</h3>
</head>
<body>
  <script>
    let message = ''
    let obj = {}
    Object.defineProperty(obj, 'show', {
      set(newVal) {
        console.log('设置show')
        message = newVal
        document.querySelector('#my-input').value = newVal
        document.querySelector('#my-title').innerText = newVal
      },
      get() {
        console.log('获取show')
        return message
      }
    })
    document.querySelector('#my-input').addEventListener('keyup', (e) => {
      obj.show = e.target.value
      console.log('视图更新,同步数据')
    })
  </script>
</body>
</html>
双向数据绑定.gif

  这样就实现了简单的双向数据绑定了,是不是很简单呢?下一篇:Vue.js 双向数据绑定原理剖析



文中有不足或者读者有疑问或更好的见解,欢迎留言讨论。
如果觉得该篇文章对您有帮助,别忘了留下您的足迹,点个赞❤噢

相关文章

网友评论

      本文标题:Object.defineProperty() 实现双向数据绑定

      本文链接:https://www.haomeiwen.com/subject/phfkrktx.html