vue2.x数据响应式的核心原理

289 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

前情提要

前面有讲过js设计模式中的观察者模式,而Vue2.x版本的响应式原理便是基于观察者模式和Object.defineProperty的数据劫持,实现数据的响应式。也是数据推动视图的渲染的源动力。那么今天就自己动手写写吧...

简述下什么是响应式

vue中响应式指的是数据改变后驱动视图更新

简述下Object.defineProperty

  • 当将一个普通的JavaScript对象传给vue实例作为data选项的时候,Object.defineProperty会将这些属性全部转化为getter和setter。
  • 是ES5中的一个新特性。这也是vue不支持低版本浏览器,比如IE8及以下等浏览器的主要原因。
  • JavaScript中每个对象都有两个属性:数据属性,和访问器属性。这两种属性平常我们是无法访问到的,只有借助Object.definePropert才可以访问和修改他们的值。在这篇文章:深入理解之JavaScript对象中有讲解到。
  • 该方法接收三个参数:目标对象,key值,一个对象。就是告诉这个方法你要给哪个对象的哪个属性做什么修改

实现响应式

  • 知道了核心技术点之后我们就来模拟实现吧

    <html>
        ... // 无关代码就不展示了。
        <body>
          <p id="pp"></p>
        </body>
        <script>
          // data属性
          const data = {
            msg: ''
          }
          // 模拟vue实例
          const vm = {}
          Object.defineProperty(vm, 'msg', {
            // 是否可枚举
            enumerable: true,
            // 是否可配置
            configurable: true,
            // 当有人获取这个属性的时候要执行的方法
            get() {
              console.log('调用了getter方法');
              return data.msg;
            },
            // 当有人给这个属性赋值的时候需要执行的方法
            set(value) {
              console.log('调用了setter方法');
              if (value === data.msg) return;
              data.msg = value;
              document.getElementById('pp').innerText = data.msg;
            }
          })
          vm.msg = 'Hello World!'; // 触发set
          console.log(vm.msg) // 触发get
        </script>
    </html>
    
  • 然后咱们看浏览器的运行结果:

    image.png

总结

  • 从上述模拟中我们可以看到vue实现数据响应式,数据推动视图的渲染的核心原理是Object.defineProperty的应用。但是该方法只能给单个的属性进行设置,data基本上不可能只有一个属性,这个时候我们该怎么办呢?
  • 当然是只能循环遍历data,然后将data中的每一个属性都在vm中使用Object.defineProperty来定义一遍喽。
  • 思考:Vue3中的数据响应式的核心原理是什么...