Vue面试系列之十二:你知道vue双向数据绑定的原理吗?

18 篇文章 1 订阅
11 篇文章 0 订阅

首先,什么是双向数据绑定?

数据变化更新视图,视图变化更新数据,即双向数据绑定;

 输入框内容变化时,data中的数据同步变化 view=>model

data中的数据变化时,文本节点的内容同步变化 model=>view

设计思想:观察者模式

Vue的双向数据绑定的设计思想为观察者模式。

Dep对象:Dependency依赖的简写,包含有三个主要属性:id,subs,target和四个主要函数addSub,removeSub,depend,notify,是观察者的依赖集合,负责在数据发生改变时,使用notify()触发保存在哎subs下的订阅列表,依次更新数据和DOM。

Observer对象:即观察者,包含两个主要属性value,dep。做法是使用getter、setter方法覆盖默认的取值和赋值操作,将对象封装为响应式对象,每一次调用时更新依赖列表,更新值时触发订阅者,绑定在对象的_ob_原型链属性上。

new Vue({
    el:"#app",
    data:{
        count:100
    },
    ...
})

初始化函数initMixin:

Vue.prototype._init=function(options){
    ...
    var vm=this;
    initLifecycle(vm);
    initEvents(vm);
    initRender(vm);
    callHook(vm,'beforeCreate');
    // 这里就是我们接下来要跟进的Vue参数
    initState(vm);
    initInjections(vm);
    callHook(vm,'created');
}

初始化参数initState:

function initState(vm){
    vm._watchers={};
    var opts=vm.$options;
    if (opts.props){initProps(vm,opts.props);}
    if (opts.methods) { initMethods(vm,opts.methods);}
    // 我们的count在这里初始化
    if (opts.data){
        initData(vm);
    }else {
        observe(vm._data={},ture};
    }
    if (opts.computed) { initComputed(vm,opts.computed);}
    if (opts.watch) { initWatch(vm,opts.watch);}

}

initData:

function initData(vm){
    var data=vm.$options.data;
    data=vm._data=typeof data==='function'
    ? data.call(vm)
    : data || {};
    if (!isPlainObject(data)){
        data={};
    }
    ...
    // observe data
    observe(data,true );
}

将data参数设置为响应式:

function observe(value,asRootData){
    if(!isObject(value)){
        return
    }
    var ob;
    if(hasOwn(value,'_ob_')&& value._ob_instanceof Observer){
        ob=value._ob_;
    }else if{
        observerState.shouldConvert &&
        !isServerRendering() &&
        (Array.isArray(value)||isplainObject(value)) &&
        Object.isExtensible(value) &&
        !value._isVue
     ){
        ob=new Observer(value);
    }
    if (asRootData && ob){
        ob.vmCount++;
    }
    return ob;
}

Observer类:

(观察者类)

var Observer=function Observer(value){
        this.value=value;
        this.dep=new Dep();
        this.vmCount=0;
        def(value,'_ob_',this);
        if(Array.isArray(value)){
            var augment=hasProto
            ? protoAugment
            :compyAugment;
            augment(value,arrayMethods,arryKeys);
            this.observeArray(value);
        }else{
            ths.walk(value)
        }
}

observerArray:

Observer.protoype.observeArray=function observeArray(items){
    for(var i=0; i=items.length;i<1;i++){
        observe(items[i])
    }
}

Dep类:

var Dep=function Dep(){
    this.id=uid$1++;
    ths.subs=[];
}

walk函数:

 Observer.prototype.walk=function walk (obj){
        var keys=Object.keys(obj)
        for(var i=0;i<keys.length;i++){
            defineReactive$$1(obj,keys[i],obj[keys[i]])
        }
    }

vues双向数据绑定所涉及的源码甚多,以上几处只是其中一部分,感兴趣的朋友可以继续钻研vue的源码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听北风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值