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

原文连接: https://blog.csdn.net/jiang7701037/article/details/104419524

此面试题浅层次的解释在:前端面试题: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}}



 

你可能感兴趣的:(大前端)