面试题:vue实现双向数据绑定的原理(附源代码)

此面试题浅层次的解释在:前端面试题:vue 的双向数据绑定原理,v-model的源码

深层次,其实就是问你vue数据绑定的原理:

1、使用Object.defineProperty进行数据劫持,把data对象,computed等里的所有属性进行数据劫持。数据劫持的意思可以看:JavaScript中的Object.defineProperty()函数

2、使用观察者模式,完成发布订阅。发布订阅者模式可以看:观察者模式

     1)、模板里使用data对象属性的dom对象都订阅。

     2)、当data对象里的属性的值发生变化时,就会发布,发布时,就改变了dom里的内容。

 

以下为源码:

     这个代码只是模拟数据绑定的原理,并没有考虑vue的虚拟dom和异步更新队列等问题。

1、模拟vue.js的代码(文件名:vue.js)


class Vue{
    constructor(obj){
        //2、数据挂载
        //2.1) 、把obj对象的每个属性,作为vue对象的属性(属性名前面加上 $)
        for(let key in obj){
            this["$"+key] = obj[key];
        }
        //2.2)、把obj.data对象的属性,作为vue对象的属性,并且要有数据劫持的功能和发布订阅的功能
        let myObserver = {};
        observer.make(myObserver);
        for(let key in obj.data){
            this["_"+key] = obj.data[key];
            Object.defineProperty(this,key,{
                //数据劫持
                set:function(newValue){
                    //数据劫持的目的是,当key发生变化时,需要渲染页面
                    this["_"+key] = newValue;
                    //数据变了,就得渲染页面,发布订阅功能
                    myObserver.publish(newValue);
                },
                get:function(){
                    return this["_"+key];
                }
            });
        }

        //2.3)、订阅(模板里的标签需要订阅data中的数据)
        let box = document.getElementById(obj.el.substring(1));//"box"
        //2.3.1)查找使用msg属性的dom元素,放在数组msgDom里
        let msgDom = [];
        for(let i=0;i {
            if(typeof element =="function"){
                element(what);
            }
        });
        
    },

    //让某个对象具备发布订阅功能
    make:function(obj){
        for(let key in this){
            obj[key] = this[key];
        }
        obj.subscribers = [];
    }
}

2、使用模拟的vue的html文件的代码




    
    
    
    Document


    
信息:{{msg}}

 

你可能感兴趣的:(vue)