zoukankan      html  css  js  c++  java
  • 浅析vue数据绑定

    前言:最近团队需要做一个分享,脚进脑子,不知如何分享。最后想着之前一直想研究一下 vue 源码,今天刚好 “借此机会” 研究一下。

    网上研究vue数据绑定的文章已经非常多了,但是自己写一遍,敲一遍demo和看别人的文章是完全不同的,so……搬运工来了

    目前数据绑定主要有以下三种实现方式:

    1.   脏值检查(angular.js)    轮询检测数据变化
    DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
    • XHR响应事件 ( $http )
    • 浏览器Location变更事件 ( $location )
    • Timer事件( $timeout , $interval )
    • 执行 $digest() 或 $apply()
    2、Object.defineProperty劫持对象的get、set,从而实现对数据的监控。 (vue)
    3、发布/订阅者模式实现数据与视图的自动同步
     
    Object.defineProperty的优点
    • “脏值检测”——数据发生变更后,对于所有的数据和视图的绑定关系进行一次检测,识别是否有数据发生了改变,有变化进行处理,可能进一步引发其他数据的改变,所以这个过程可能会循环几次,一直到不再有数据变化发生后,将变更的数据发送到视图,更新页面展现 
    • Object.defineProperty() 监控对数据的操作,可以自动触发数据同步。并且,由于是在不同的数据上触发同步,可以精确的将变更发送给绑定的视图,而不是对所有的数据都执行一次检测。
     
    Object.defineProperty的用法
    var a = {};

    Object.defineProperty(a, "b", {
    
        set: function (newValue) {
        
            console.log("我被赋值了!" + newValue);
    
         },
    
        get: function () {
        
            console.log("我被取值了!");
        
            return 2   
        }
})

    a.b = 3; //我被赋值了!
    console.log(a.b);   //我被取值了!       //打印 2            
    由上面的例子看出,Object.defineProperty  传人3个参数
    第一个: a对象
    第二个: a对象里面的b属性
    第三个: 属性比较多,列举有用的 value,set,get,configurable
     
     
    数据绑定原理:
    1、实现一个数据监听器Observer,对数据对象的所有属性进行监听,如有变动则拿到最新值并通知 dep数组
    2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据
    3、实现一个dep数组 ,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,更新视图
     
     
    1. 实现observer
    var data = {name: 'beidan'};

    observe(data);

    data.name = 'test'; // 监听到值变化了  beidan  变成  test

function observe(data) {
    
         if (!data || typeof data !== 'object') {
        
           return;
    
         }
    
         // 取出所有属性遍历    
        Object.keys(data).forEach(function(key) {
    
             defineReactive(data, key, data[key]);

      });
    }
    function defineReactive(data, key, val) {


        Object.defineProperty(data, key, {

            enumerable: true, // 可枚举        
                    configurable: false, // 不能再define        
                    get: function() {
            
                        return val;
        
                    },
        
                    set: function(newVal) {
            
                        console.log('监听到值变化了 ', val, ' 变成 ', newVal);

                        val = newVal;
        
                    }
    
            });
    }                        

    2. 维护一个数组

    function Dep() {
   
         this.subs = [];
    }
    
Dep.prototype = {
    
        addSub: function (sub) {
        
           this.subs.push(sub);
    
        },
   
         notify: function (val) {
       
             this.subs.forEach(function (sub) {
            
                sub.update(val)
        
            });
    
    }
};
    
    function defineReactive(data, key, val) {
       Object.defineProperty(data, key, {
         ……
          set: function(newVal) {
               if (val === newVal) return;
                console.log('监听到值变化了 ', val, ' 变成 ', newVal);
                val = newVal;
                dep.notify(val); // 通知所有订阅者     
          } 
        });
    }                

    3. compile

    bindText: function () {
    
        var textDOMs = this.el.querySelectorAll('[v-text]'),
bindText,_context = this;

   
        for (var i = 0; i < textDOMs.length; i++) {
         
           bindText = textDOMs[i].getAttribute('v-text');
  
           textDOMs[i].innerHTML = this.data[bindText];

        
           var val = textDOMs[i]

        
           var up = function (text) {
           
             val.innerText = text
        
           }
    
       _context.dep.addSub({
            
                value: textDOMs[i],
            
                update: up
       
           });
   
     }
},                    
     
     
    最后,附上源码 github   https://github.com/beidan/vue_bind
     
     
    参考链接:
    http://www.cnblogs.com/LuckyWinty/p/6102913.html
    http://www.cnblogs.com/kidney/p/6052935.html?utm_source=gold_browser_extension
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    dedecms织梦自定义表单发送到邮箱-用163邮箱发送邮件
    DedeCMS实现自定义表单提交后发送指定QQ邮箱法
    什么是授权码,它又是如何设置?
    telnet配置和telnet用法
    linux利用sendmail发送邮件的方法
    SSH会话连接超时问题
    dede 提交表单 发送邮件
    a 标签中 写页面刷新代码
    织梦dede在首页调用留言本
    PHP通过Thrift操作Hbase
  • 原文地址:https://www.cnblogs.com/beidan/p/6290923.html
Copyright © 2011-2022 走看看