• 数据双向绑定。类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]
        }
    }
  • 相关阅读:
    转载 如何去掉超链接文字下的下划线
    Fedora 15安装 VirtualBox 4.1
    庆祝开通!
    Delphi直接读写XML修改版
    Perforce的资料一点也没查到
    AxWebBrowser的Navigate2方法写参数的偷懒方法
    腾讯2012实习生面试
    如何让div在IE6下自适应
    PhpStorm修改字体
    监听url
  • 原文地址:https://www.cnblogs.com/yihuite-zch/p/11543271.html
Copyright © 2020-2023  润新知