一、MVVM响应式原理:

   vue是采用数据劫持配合发布者-订阅者的模式的方式,通过Object.defineProperty()来劫持各个属性的getter和setter,在数据变动时,发布消息给依赖收集器(dep中的subs),去通知(notify)观察者,做出对应的回调函数,去更新视图。

在这里插入图片描述

MVVM作为绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer,Compile之间的通信桥路,达到数据变化=>视图更新;视图交互变化=>数据model变更的双向绑定效果。

二、数据双向绑定

有Object.defineProperty() 和 Proxy 对象(代理)两种方式来实现数据双向绑定。 用对数据的劫持操作的方式。当访问或者修改某个对象的某个属性的时候,通过一段代码进行拦截行为,然后进行额外的操作,然后返回结果。

双向绑定原理: 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式, 通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

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

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>数据双向绑定</title>
</head>
<body>
  <input type="text" id="in">
  <span id="p1"></span>
  <script>
    var inputName = document.getElementById('in');
    var spanName = document.getElementById('p1');

    var student = {};
    Object.defineProperty(student, 'name', {
      get: function() {
        return val;
      },

      set: function(val) {
        spanName.innerHTML = val;
      }
    });
    inputName.oninput = function() {
      student.name = this.value;
    }
  </script>
</body>
</html>

使用Proxy(代理)实现数据双向绑定:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>数据双向绑定</title>
</head>
<body>
  <input type="text" id="in">
  <span id="p1"></span>
  <script>
    var inputName = document.getElementById('in');
    var spanName = document.getElementById('p1');

    var student = {};
    var proxy = new Proxy(student, {
        get: function(target, prop) {
          return target[prop];
        },

        set: function(target, prop, value) {
          target[prop] = value;
          observer();
        }
      });

      function observer() {
        inputName.value = student.name;
        spanName.innerHTML = student.name;
      }

      inputName.oninput = function() {
        proxy.name = this.value;
      }
  </script>
</body>
</html>

二者的区别:

Vue2.0中使用的是Object.defineProperty实现对属性的监听,
缺点

  • 一定要克隆一个新的对象进行操作,否则就会造成死循环;
  • 如果有多个属性,那么就要定义多个Object.defineProperty去分别监听每一个属性。

Vue3.0使用了ES6的新语法,用到了Proxy去实现监听,

  • 省去克隆对象的步骤;
  • 不管有多个属性只需要定义一次Proxy就可以实现多对象的监听,不同分别定义。
Logo

前往低代码交流专区

更多推荐