zoukankan      html  css  js  c++  java
  • 双向数据绑定原理

    几种实现双向绑定的做法:

        目前几种主流的mvc(vm)框架都实现了单项数据绑定,而我所理解的双向数据绑定,无非就是在单项数据绑定的基础上给输入元素input textare等添加了change(input)事件,来动态修改model和view,并没有多高深。所以无须介怀是实现的单项或者双向绑定,实现数据绑定 大致几种:

    1. 发布者-订阅者(backbone.js);
      1. 一般通过sub,pub的方式实现数据和视图的绑定监听,更新数据的方式通常是  vm.set('property',vlue);

     

    1. 脏值检查(angular.js);
      1. Angular.js是通过脏值检测的方式比对数据是否有变更。来决定是否更新视图,最简单方式是通过setinterval()定时轮询检测数据变动,当然angular只是在指定的事件触发时进入脏值检测:
        1.   
        2. Ng-click
        3.   
        4. $http
        5.   
        6. $location
        7.   
        8. $timeout $interval
        9.   
        10. $digest()||$apply()
    2. 数据劫持(vue.sj);

    Vue.js则采用数据劫持+发布者订阅者模式的方式,通过0bject.defineProperty()来劫持各个属性的setter  getter,在数据发生改变时发布消息给订阅者,触发相应的监听回调。具体整理:

    vue是通过数据劫持的方式来做数据绑定,其中核心方法是通过object,defineProperty()来实现对属性的劫持,达到监听数据变动的目的,无疑这个方法是本文中最重要,最基础的内容之一。

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

    实现mvvm双向数据绑定,步骤:

    1. 实现一个数据监听observer(观察者),能够对数对象的所有属性进行监听,如果有变动可拿到最新值并通知订阅者;
      1. 利用object.defineProperty()来监听属性变动;那么将需要observer的数据对象进行遍历,包括子属性对象的属性,都加上setter和getter这样的话给这个对象的某个值赋值,就会触发setter,从个人监听到数据变化。
      2. 监听到后,怎末通知订阅者呢?所以需要实现一个消息订阅器:维护一个数组,用来手机订阅者,数据变动会触发notify,再调用订阅者的update方法。watcher
    2. 实现一个指令解析器Compile,对每个元素的指令进行进行扫描和解析,根据指令模板替换数据,以及绑定相应数据;
      1. complile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定跟新函数,方便随时更新视图。
      2. 因为遍历解析的过程有多次dom节点,为了提高性能和效率,会先将节点el转换为文档碎片进行解析编译(js对象虚拟DOM),解析完成后再添加回原来的真实dom节点中。
    3. 实现watcher,作为连接observer和compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定相应的会回调函数,从而跟新试图。
      1. 在自身实例化时往属性订阅器dep里面添加自己;
      2. 自身必须有一个update()方法;
      3. 代属性变动dep.notice()通知时,能调用自身的update()方法,并触发complie中绑定的回调.
    4. mvvm入口函数,整合以上三者;达到数据变化-》视图更新;视图交互变化(input)->数据model变更的双向数据绑定效果;

    MVVM:model   view   view model

    数据双向绑定,简化了页面和业务的依赖,解决了数据频繁更新。MvvM在使用当中,利用双向数据绑定计数,使得Model变化时,viewModel  会自动更新,而viewModel 变化时,view也会自动变化。

    双向数据绑定原理:

    采用数据劫持:发布者和订阅者模式的方式,通过object.defineProperty()来劫持各个属性的setter和getter,在数据变动时发布消息给订阅者,出发相应的监听回调;具体步骤:

    1. 当把一个普通的js对象传给VUE实例来作为他的data选项时,vue将遍历他的属性,用object.defineProperty都加上setter和getter方法,这样给这个对象的某个值赋值,就会出发setter,那么就能监听到数据变化;
    2. compile解析模板指令
    3. Watcher 订阅者是observer和compile之间的桥梁,主要做的事:
      1. 在自身实例化时往属性订阅器(dep)里添加自己;
      2. 子集必须有一个update()方法
      3. 待属性变动dep.notice通知时,调取update()方法,并触发compile绑定的回调,则功成身退。
      4. MvvM作为数据的绑定入口,整合observer compile watcher三者:
        1.   
        2. 通过observer来监听自己的model数据变化;
        3.   
        4. 通过compile来解析编译模板指令
        5.   
        6. 最终利用wacher搭起observer和compile之间的通信桥梁,
        7.   
        8. 达到数据变化=>视图跟新;视图交互变化(input)=>数据model变更的双向数据效果。

    proxy相比defineProperty优势:

    Object.defineProperty()三个主要问题:

    1. 不能监听数组变化;
    2. 必须遍历对象的每个属性;
    3. 必须生层次遍历嵌套的对象;

    而  ES5的proxy新加入,特点:

    1. 针对对象:针对整个对象而不是对象的某个属性,所以也就不需要keys进行遍历
    2. 支持数组:proxy不需要对数组进行重载,省去了众多hack,减少代码等于减少维护成本。

    vue中的虚拟DOM:

              虚拟DOM本质就是一个和真实DOM结构类似的Js对象;

            虚拟DOM可以提高浏览器的渲染速度。对比操作Js对象,比操作真实的DOM消耗的性能少的多,特别时                             频繁的操作DOM时,优势彰显的更加明显。

     虚拟DOM步骤:

    1.  在页面首次渲染时,将要渲染的数据全部加载到虚拟DOM中,而后在一次性渲染到真实的DOM上;
    2. 数据变动时,额外生成一个虚拟DOM树,
    3. 通过Diff算法对比修改的部分,而后将修改部分渲染到真实的DOM中;
    4. 释放内存。
  • 相关阅读:
    CSS基础——基本单位
    CSS基础——表格
    CSS基础——列表
    Single-Source Shortest Paths
    Maximum Flow
    Breadth-First Search
    Depth-First Search (III)
    Depth-First Search (II)
    Depth-First Search (I)
    Simple Complete Search
  • 原文地址:https://www.cnblogs.com/yancongyang/p/11170214.html
Copyright © 2011-2022 走看看