• 技术文章 >web前端 >Vue.js

    解析vue中observer数据双向绑定原理(代码分享)

    奋力向前奋力向前2021-08-24 10:18:13转载247

    之前的文章《浅析JS中Array对象一些操作方法(附代码)》中,给大家了解了JS中Array对象一些操作方法。下面本篇文章给大家了解vue中observer数据双向绑定原理,伙伴们来看看一下。

    vue数据双向绑定原理和简单的实现

    微信截图_20210823091733.jpg

    1)vue数据双向绑定原理-observer

    2)vue数据双向绑定原理-wather

    3)vue数据双向绑定原理-解析器 Complie

    vue数据双向绑定原理, 和简单的实现

    去他喵的底层原理,框架内核,老夫写代码只用Jquery

    个人觉得,不论是否是长期与之交集,还是应该看下核心的东西。多多了解高人是如何实现的,这样才能学到更多的知识,才能成长进步。倘若某天被人问起,某种框架内裤,其实现原理,那么只能是一脸懵逼了。

    实现数据绑定的做法有大致如下几种:

    vue.js则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

    假如写过C#winform自定义控件的,我想更好理解之后的逻辑和实现原理

    C#中当控件的某个属性发生了变化,就刷新视图

    priveate int  a ;
    public  int A
    {
       get { return a; }
       set { if(a!=value){a = value; Invalidate(); } }
    }
    
    # 当a的值发生变化, 就重绘视图

    再来看看Object.defineProperty(obj, prop, descriptor) 方法

    地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

    Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。

    descriptor

    先来实现一个简单数据劫持

    var A = {};
    var a = "";
    Object.defineProperty(A, "a", {
      set: function (value) {
        a = value;
      },
      get: function () {
        return "My name is " + a;
      },
    });
    
    A.a = "chuchur";
    console.log(A.a); // My name is chuchur

    不光是这么简单,来看下vue的代码

    <div id="app">
      <input type="text" v-model="word" />
      <p>{{word}}</p>
      <button v-on:click="sayHi">change model</button>
    </div>
    <script>
      var vm = new Vue({
        el: "#app",
        data: {
          word: "Hello World!",
        },
        methods: {
          sayHi: function () {
            this.word = "Hi, everybody!";
          },
        },
      });
    </script>

    已经实现的简单的数据劫持,那么有多个属性,就要实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,还需要一个订阅器Dep来收集这些属性的变动来通知订阅者

    元素节点的v-model,v-on:click,就需要实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数

    最后实现一个订阅者Watcher,作为连接ObserverCompile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

    大概的流程图如下:

    微信截图_20210823093103.jpg

    实现Observer

    将需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上settergetter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

    // observe
    function observe(data) {
      if (data && typeof data === "object") {
        // 取出所有属性遍历
        Object.keys(data).forEach(function (key) {
          defineReactive(data, key, data[key]);
        });
      }
      return;
    }
    
    function defineReactive(data, key, val) {
      observe(val); // 监听子属性
      Object.defineProperty(data, key, {
        enumerable: true, // 可枚举
        configurable: false, // 不能再define
        get: function () {
          return val;
        },
        set: function (value) {
          console.log("监听到值变化了: ", val, "==>", value);
          val = value;
        },
      });
    }
    var A = {
      fristName: "chuchur",
      age: 29,
    };
    observe(A);
    
    A.fristName = "nana"; //监听到值变化了:  chuchur ==> nana
    A.age = 30; //监听到值变化了:  29 ==> 30

    这样就实现了多个属性的监听,接下来就是实现订阅器Dep,当这些属性变化的时候,触发通知notify,告诉执行订阅者执行更新函数

    //Dep
    function Dep() {
      this.subs = [];
    }
    Dep.prototype = {
      addSub: function (sub) {
        this.subs.push(sub);
      },
      notify: function () {
        this.subs.forEach(function (sub) {
          sub.update();
        });
      },
    };

    把订阅器植入到监听器里

    function defineReactive(data, key, val) {
    
      var dep = new Dep()
      observe(val); //监听子属性
      Object.defineProperty(data, key, {
        set: function(value) {
          dep.notify() //发出通知, 我被改变了
        }
      });
    
    }

    至此,简陋的监听器就实现完成了,接下来继续完成Watcher

    推荐学习:vue.js教程

    以上就是解析vue中observer数据双向绑定原理(代码分享)的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:禅境花园,如有侵犯,请联系admin@php.cn删除
    专题推荐:vue
    上一篇:浅谈Vue中v-for,key取值影响过渡效果和动画效果(代码详解) 下一篇:一文了解vue中watcher数据双向绑定原理(附代码)
    大前端线上培训班

    相关文章推荐

    • vue如何动态增加css• Vue的响应式原理是什么?• 分享五个好用的VueUse函数,一起用起来吧!• 分享golang和vue3开发的一个im应用• 浅谈Vue中v-for,key取值影响过渡效果和动画效果(代码详解)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网