数据双向绑定。类vue底层实现原理


<!
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <div> <div v-text="myText"></div> </div> <input type="text" v-model="myText"> </div> <script src="likeVue.js"></script> <script> let vm=new Vue({ el:'#app', data:{ myText:'这是数据驱动' } }) </script> </body> </html>
class Vue {
    constructor(setting){
        this.$el=document.querySelector(setting.el);
        this.$data=setting.data;
        //创建容器保存订阅者信息
        this._directive={},this.newObj={};
        this.Observer(this.$data);
        this.Complie(this.$el);
    }
    //解析指令
    Complie(el){
        let nodes =el.children;
        for(let i=0;i<nodes.length;i++){
            let node =nodes[i]
            if(node.hasAttribute('v-text')){
                let attrval=node.getAttribute('v-text');
                //push ??订阅者
                this._directive[attrval].push(new Watcher(node,this,attrval,'innerHTML'));
            }
            if(node.hasAttribute('v-model')){
                let attrval=node.getAttribute('v-model');
                //push ??订阅者
                this._directive[attrval].push(new Watcher(node,this,attrval,'value'));
                //dom变化更新数据
                node.addEventListener('input',()=>{
                    this.$data[attrval]=node.value;
                    this.newObj[attrval]=node.value;
                    // this._directive[attrval].forEach(item=>{
                    //     item.update()
                    // });
                })
            }
            if(node.children.length){
                this.Complie(node)
            }
        }
    }
    //劫持数据
    Observer(data){
        for (let key in data) {
            this._directive[key]=[];
            // let val =data[key];
            // let watcher =this._directive[key];
            // Object.defineProperty(this.$data,key,{
            //     get:function(){
            //         return val;
            //     },
            //     set:function(newVal){
            //         if(newVal!==val){
            //             val =newVal;
            //             watcher.forEach(item=>{
            //                 item.update()
            //             })
            //
            //         }
            //     }
            // })
        }
        let self=this;
        this.newObj = new Proxy(data, {
            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);
                self._directive[key].forEach(item=>{
                    item.update();
                })
                return Reflect.set(target, key, value, receiver);
            },
        });
    }
}
//订阅者-->负责自己更新本身状态
class Watcher{
    constructor(el,vm,exp,attr){
        this.el=el;
        this.vm=vm;
        this.exp=exp;
        this.attr=attr;
        this.update();
    }
    update(){
        this.el[this.attr]=this.vm.$data[this.exp]
    }
}

 

posted @ 2019-09-18 16:24  *朝晖  阅读(373)  评论(0编辑  收藏  举报