美文网首页
ES5和ES6拦截属性实现MVVM

ES5和ES6拦截属性实现MVVM

作者: DoEmpty | 来源:发表于2019-07-12 09:33 被阅读0次
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="vmDom">
        <input type="text" name="" v-model="name" placeholder="请输入姓名">
        姓名是:<label v-text="name"></label>
        <div>
            <input type="text" name="" v-model="age" placeholder="请输入年龄">
            年龄是:<label v-text="age"></label>
        </div>
    </div>
</body>
<script>
    class MVVM{
        constructor(options){
            this.options = options;
            this.$data = options.data;
            this.$el = document.querySelector(options.el);
            
            //ES6 Proxy用法
            this.$proxy = {};
            //订阅者存放容器 采用{指令1:[],指令2:[]}的格式 按指令进行分类,不干扰不相干指令,也就是个别渲染而非全部渲染
            this._directive = {};
            this.Observer(this.$data);
            this.Compile(this.$el);
        }

        //劫持数据
        Observer(data){
            // ES5用法
            // for(let key in data){
            //     this._directive[key] = [];
            //     let val = data[key];
            //     let wachers = this._directive[key];
            //     Object.defineProperty(this.$data,key,{
            //         get(){
            //             return val;
            //         },
            //         set(newVal){
            //             if(newVal == val){
            //                 val = newVal;
            //                 return;
            //             }
            //             val = newVal;
            //             wachers.forEach(w =>{
            //                 w.update();
            //             });
            //         }
            //     })
            // }


            //ES6 Proxy用法
            for(let key in data){
                this._directive[key] = [];
            }
            const self = this;
            this.$proxy = new Proxy(this.$data,{
                set(target,property,newVal){
                    if(target[property] === newVal){
                        return;
                    }
                    target[property] = newVal;
                    let wachers = self._directive[property];
                    wachers.forEach(w =>{
                        w.update();
                    });
                    return true;
                }
            });
        }

        //解析指令
        Compile(el){
            for(let i=0;i<el.children.length;i++){
                let item = el.children[i];
                if(item.children.length > 0){
                    this.Compile(item);
                }

                if(item.hasAttribute("v-text")){
                    let attrVal = item.getAttribute("v-text");
                    // ES5用法
                    // this._directive[attrVal].push(new Wacher(item,"innerText",this.$data,attrVal));
                    this._directive[attrVal].push(new Wacher(item,"innerText",this.$proxy,attrVal));
                }
                
                if(item.hasAttribute("v-model")){
                    let attrVal = item.getAttribute("v-model");
                    // ES5用法
                    // this._directive[attrVal].push(new Wacher(item,"value",this.$data,attrVal));
                    this._directive[attrVal].push(new Wacher(item,"value",this.$proxy,attrVal));
                    item.addEventListener('input', e => {
                        // ES5用法  
                        // this.$data[attrVal] = item.value;
                        this.$proxy[attrVal] = item.value;
                    });
                }
            }
        }
    }

    //订阅者
    class Wacher{
        constructor(el,attr,vm,key){
            this.el = el;
            this.attr = attr;
            this.vm = vm;
            this.key = key;
            this.update();
        }

        update(){
            this.el[this.attr] = this.vm[this.key];
        }
    }

    const vm = new MVVM({
        el:'#vmDom',
        data:{
            name:'kerry',
            age:28
        }
    });
</script>
</html>

相关文章

  • ES5和ES6拦截属性实现MVVM

  • Proxy代理

    代理 ES5 代理方式 ES6 Proxy ES6 Reflect 常用拦截方法 get拦截对象属性的读取,比如p...

  • React中ES6和ES5的不同之处

    组件类的定义 es5 es6 状态初始化 es5 }) es6 属性初始化 es5 es6 组件抛出 es5 es...

  • React-Native之Props(属性)

    效果如下: 小结如下: 1.定义组件的属性类型和默认属性(ES5 和ES6中的区别) 在ES5里,属性类型和默认属...

  • 设计模式-单例模式

    es5实现方式 es6实现方式

  • ES6 类和ES5 构造函数

    ES5的构造函数和ES6的Class区别 ES5的构造函数的原型上的属性和方法可以遍历/ES6 不能够遍历 ES6...

  • js:class类

    一、继承 1. ES6的继承 2. es5实现 重点代码Animal.call(this,props)继承父类属性...

  • 用ES5和ES6实现继承

    ES5 prototype实现继承 ES6 写法

  • ES5、ES6继承

    ES5、ES6继承方式 继承的目标: 父类公有属性和方法为子类公有属性和方法父类私有属性和方法为子类私有属性和方法...

  • es6 对象 笔记

    创建对象 es5 es6 对象的key 对象属性的缩写 对象的动态属性名 对象属性的get()和set() 对象的...

网友评论

      本文标题:ES5和ES6拦截属性实现MVVM

      本文链接:https://www.haomeiwen.com/subject/udiskctx.html