美文网首页
MVVM双向数据绑定的个人理解

MVVM双向数据绑定的个人理解

作者: revert | 来源:发表于2019-04-23 16:19 被阅读0次

AngularJS 的脏检查机制

AngularJS的双向数据绑定采用的脏检查机制,所谓“脏检查”,就是检测到数据与之前不一致,有变化,这时候就认为数据是“脏”的,然后把不一致的数据变更为较新的值,直到没有新的数据变动。

通常UI事件、ajax请求后的数据处理 或者 timeout 延迟事件会触发这个脏检查这个过程的实现,主要是靠 $watch$digest 两个重要的函数。

$watch

每当有变量通过$scope对象和页面UI绑定,就会增加一个watch对象

watch = {
    name:'',      //当前的watch 对象 观测的数据名
    getNewValue:function($scope){ //得到新值
        ...
        return newValue;
        },
    listener:function(newValue,oldValue){  // 当数据发生改变时需要执行的操作
        ...
    }
}

$watch函数会收集所有的watch对象到$$watchList数组中,然后等待$digest遍历$$watchList中的listener,用代码表示更为直观

$scope.prototype.$watch = function(name,getNewValue,listener){
    var watch = {
       name:name,
       getNewValue : getNewValue,
       listener : listener
    };

    this.$$watchList.push(watch);
}

挂载到$scope原型上是为了每个Scope实例上存储这些函数。

$digest

$digest函数的作用就是在触发脏检查的时候,遍历之前push到$$watchList中的watch.listener,用代码解释就是这样:

$scope.prototype.$digest = function(){
    var list = this.$$watchList;
    for(var i = 0,l= list.length;i++){
        var watch = list[i];
        var newValue = watch.getNewValue(this);
        // 在第一次渲染界面,进行一个数据呈现.
        var oldValue = watch.last;
        if(newValue!=oldValue){
            watch.listener(newValue,oldValue);
        }
        watch.last = newValue;
    }
}

watch.last用于存储上一次的值,当newValue!=oldValue时,就认为数据上“脏”的,就会递归调用$digest,保证所有数据都一致。$digest至少会调用两次,才能确保数据是干净的,当然也不会无休止的递归下去,递归10次就会抛出异常了,这种情况说明业务数据过于复杂(或者代码特别渣渣),需要开发人员优化一下了。

Vue的数据劫持模式

vue的双向数据绑定,采用数据劫持模式,核心是Object.defineProperty,Vue3.0的核心要变成proxy了。

通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化

Object.defineProperty

对于vue({data:{}}),data对象上的所有属性,都会被Object.defineProperty劫持,增加对应的gettersetter,结合发布订阅模式,就可以对数据检测赋值,这里说明一下数据劫持部分,代码如下:


function observe(data){ 
    if(typeof data !== 'object'){//不是对象不进行数据劫持
        return
    }
    return new Observe(data);
}
 
//将model->vm.data
function Observe(data){
    for(let key in data){//遍历所有属性进行劫持
        let val = data[key];
        observe(val);//深入递归数据劫持exp:data:{a:{a:3},b:5}}
        Object.defineProperty(data,key,{
            enumerable: true,
            get(){
                return val//此时的val已经进行了数据劫持,exp:{a:3}
            },
            set(newVal){
                if(newVal === val ){//值不变则返回
                    return
                }
                val = newVal;
                observe(newVal);//新赋的值也必须进行数据劫持
            }
        }
    }
}

Object.defineProperty缺点是无法监听数组变化,vue是单独对数组进行了常用方法的hack。

proxy

Proxy在ES2015规范中被正式发布,它在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写,我们可以这样认为,Proxy是Object.defineProperty的全方位加强版,proxy可以监听整个对象,无论对象内部的属性是数组还是新对象。

proxy 劫持的简单例子:

const newObj = new Proxy(obj, {
  get: function(target, key, receiver) {
    console.log(`getting ${key}!`);
    return Reflect.get(target, key, receiver);
  },
  set: function(target, key, value, receiver) {
    console.log(target, key, value, receiver);
    return Reflect.set(target, key, value, receiver);
  },
});

被劫持的对象会被添加对应的watcher,以此实现双向数据绑定。

参考文章:

相关文章

  • 双向数据绑定

    双向数据绑定 双向数据绑定基于MVVM框架,vue属于MVVM框架 MVVM:M等于model,V等于view,即...

  • Vue2 数据双向绑定原理解析-简易版(个人笔记)

    一、什么是 MVVM 数据双向绑定 MVVM 数据双向绑定主要是指:数据变化更新视图,视图变化更新数据,如下图所示...

  • MVVM双向数据绑定的个人理解

    AngularJS 的脏检查机制 AngularJS的双向数据绑定采用的脏检查机制,所谓“脏检查”,就是检测到数据...

  • Vue题目

    Vue 1、vue解决了什么问题 解决了数据和控件双向绑定问题 2、MVVM的理解 MVVM是Model-View...

  • Vue MVVM 原理实现

    核心原理 MVVM 双向数据绑定, 数据驱动视图 Vue 实现 MVVM 采用 数据劫持 + 发布订阅模式 : ...

  • JavaScript实现双向绑定的三种方式

    前端数据的双向绑定方法 前端的视图层和数据层有时需要实现双向绑定(two-way-binding),例如mvvm框...

  • vue双向数据绑定

    剖析Vue原理、实现双向绑定MVVM 几种实现双向绑定的做法 目前几种主流的mvc(vm)框架都实现了单向数据绑定...

  • angular双向绑定

    MVVM的核心机制就是双向绑定。React、Vue、Angular的双向绑定,都是基于MVVM的设计模式。 双向绑...

  • Vue面试考点之响应式原理

    我们都知道Vue通过MVVM思想实现数据的双向绑定,数据驱动页面视图。那它到底是如何进行双向绑定的呢? Vue数据...

  • AngularJS双向绑定之脏检查机制

    一、Angular双向绑定(MVVM) 视图的改变能反映到数据模型上,数据的更改也能在界面呈现 二、触发双向绑定 ...

网友评论

      本文标题:MVVM双向数据绑定的个人理解

      本文链接:https://www.haomeiwen.com/subject/ytjvgqtx.html