zoukankan      html  css  js  c++  java
  • vue mvvm原理与简单实现 -- 上篇

    Object.defineProperty介绍--
        let obj = {};
        Object.defineProperty(obj,'school',{
            configurable : true, // 属性能否被删除
            //writable : true, // 属性能否被修改
            enumerable : true, // 属性能否枚举
            //value : 'zfpx', // 设置属性值
    
            set : function(value){
                console.log(value); // obj.school赋值时, 调用set() 方法
            },
            get : function(){
                return 'zfpx'; // 获取 obj.school 的值时,调用 get() 方法
            }
        })
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <body>
    <div id="app">
        <p>{{a.a}}</p>
        <div>{{b}}
    <div>{{b}}</div>
        </div>
    </div>
    </body>
    <!-- mvvm 双向数据绑定
    vue 数据劫持+发布订阅模式
    不兼容低版本 Object.defineProperty -->
    <script>
    
        (function(window,document){
            function ZF(options = {}){
                this.$options = options; // 将所有的属性挂载在 $options 上
                let data = this._data = this.$options.data;
                this.observe(data);
                for(let key in data){ // 把data属性通过Object.defineProperty的方式定义属性
                    // 数据代理
                    // this代理了this._data
                    Object.defineProperty(this,key,{
                        enumerable : true, // 可枚举
                        get: function(){
                            return this._data[key];
                        },
                        set: function(newVal){ // 更改值的时候
                            this._data[key] = newVal;
                        }
                    });
                }
                this.Compile(options.el,this);
            }
            // 编译
            ZF.prototype.Compile = function(el,vm){
                vm.$el = document.querySelector(el);
                let fragment = document.createDocumentFragment();
                while(child = vm.$el.firstChild){  // 将app中的内容 移入内存中
                    fragment.appendChild(child);
                }
                // 循环每一层
                Array.from(fragment.childNodes).forEach(function(node){
    
                    let text = node.textContent;
                    let reg = /{{(.*)}}/;
        
                    if( reg.test(text)){
                        let arr = RegExp.$1.split('.');
                        let val = vm;
                        console.log(node.childNodes)
                        console.log(arr)
                        arr.forEach(function(k){
                            val = val[k];
                        })
                        // 替换
                        node.textContent = text.replace(/{{(.*)}}/,val)
                    }
                    //node.textContent.textContent(12)
    
                })
                vm.$el.appendChild(fragment);
            }
            // 观察对象给对象增加ObjectDefineProperty;
            ZF.prototype.observe = function(data){
                //console.log(data)
                return new Observe(data);
                
            }
            function Observe(data){
                for(let key in data){ // 把data属性通过Object.defineProperty的方式定义属性
                    let val = data[key];
                    // 递归
                    if(typeof val === 'object'){
                        Observe(val);
                    }
                    Object.defineProperty(data,key,{
                        enumerable : true, // 可枚举
                        get: function(){
                            return val;
                        },
                        // 数据劫持
                        set: function(newVal){ // 更改值的时候
                            if(newVal === val){
                                return;
                            }
                            if(typeof newVal === 'object'){
                                Observe(newVal);
                            }
                            val = newVal; //
                        }
                    });
                }
            }
            window.ZF = ZF;
    
        })(window,document);
    
        let zf = new ZF({
            el : "#app",
            data : {a:{a:'是a'},b:'是b'},
        })
    
    
        
    </script>
    </html>
  • 相关阅读:
    SpringMVC 使用JSR-303进行校验 @Valid
    Hibernate Tools生成注释
    大型网站架构演变和知识体系(转载)
    eclipse从数据库逆向生成Hibernate实体类
    性能测试公众号,欢迎你的加入~
    mysql使用druid监控配置
    (转)面试为什么需要了解JVM
    (转)什么是缓存击穿?
    Mysql推荐使用规范(转)
    java应用监控工具
  • 原文地址:https://www.cnblogs.com/cl94/p/12235968.html
Copyright © 2011-2022 走看看