zoukankan      html  css  js  c++  java
  • 对象的属性类型 和 VUE的数据双向绑定原理

      如[[Configurable]] 被两对儿中括号 括起来的表示 不可直接访问他们

    修改属性类型:使用Object.defineProperty()  //IE9+  和标准浏览器  支持

    查看属性的数据特性:Object.getOwnPropertyDescriptor()

    上图输出的就是

    属性类型分为两种:数据属性和访问器属性。

    数据属性:有四个

      [[Configurable]]:表示能否通过delete删除属性,能否修改属性特性、能否修改访问器属性 如果修改成false 就不能在修改回来并且再次使用Object.defineProperty()修改属性特性只能修改[[writable]] 默认true

      [[Enumerable]]:表示能否表示目标属性是否可遍历  默认true

    for in、Object.keys 和 JSON.stringify()不能返回属性

      [[writable]]:表示能否修改属性值  默认true

      [[value]]:这个位置是属性值,属性值默认undefined 这就是你没有给值时候为什么默认undefined

    访问器属性:

       访问器属性:

        [[get]]:获取属性值的时候触发get函数

        [[set]]:设置属性值时触发set函数

        VUE2.0的数据双向绑定就是使用的Object.defineProperty()重写set和get方法实现的,VUE3.0是使用es6中的proxy代理实现的了。

        下面附赠VUE2.0的数据双向绑定原理(简易版因为这里没有虚拟dom层)

     //发布者
        class Vue{
            constructor(options){
                //new Vue时传进来的对象
                this.options = options;
                //对象下的data
                this.$data = options.data;
                //根据#el 获取到具体的dom元素
                this.$el = document.querySelector(options.el);
                //存放订阅者
                this._directive={};
                this.Observer(this.$data);
                this.Compile(this.$el);
            }
    
            //劫持数据
            Observer(data){
                for(let key in data){
                    //_directive[inputText(key)] =[] []这里面存存储 订阅者
                    // 也就是都哪些dom元素使用inputText变量了
                    this._directive[key] = [];
                    //inputText(key)变量数据
                    let val = data[key];
                    //获取到订阅inputText(key)dom元素集合
                    let _obj = this._directive[key];
                    //defineproperty 核心方法
                    Object.defineProperty(this.$data,key,{
                        get:function () {
                            return val;
                        },
                        set:function(newVal){
                            //判断数据是否改动
                            if(val!==newVal){
                                val=newVal;
                                //便利订阅者 所有订阅者执行更新 也就是Watcher(下的update)
                                _obj.forEach(function (el) {
                                    el.update();
                                })
                            }
                        }
                    })
                }
            }
    
            //解析指令
            Compile(el){
                let nodes = el.children;
                for (let i = 0; i<nodes.length;i++){
                    let node = nodes[i];
                    //判断当前元素下是否有 子元素
                    if(node.children.length){
                        //递归出所有#app下 dom元素
                        this.Compile(node);
                    }
                    //dom元素是否有v-text属性(指令)
                    if(node.hasAttribute('v-text')){
                        let attrValue = node.getAttribute('v-text');
                        //向订阅者容器 添加订阅者
                        this._directive[attrValue].push(new Watcher(node,this,attrValue,'innerHTML'));
    
                    }
                    if(node.hasAttribute('v-model')){
                        let attrValue = node.getAttribute('v-model');
                        //向订阅者容器 添加订阅者
                        this._directive[attrValue].push(new Watcher(node,this,attrValue,'value'));
                        let _this = this;
                        node.addEventListener('input',function () {
                            //vue实例下的data数据 赋值
                            _this.$data[attrValue] = this.value;
                        },false)
                    }
                }
            }
        }
        //订阅者
        class Watcher{
            constructor(el,vm,exp,attr){
                //dom元素
                this.el = el;
                //vue实例对象
                this.vm = vm;
                //data下的变量名字
                this.exp = exp;
                //根据指令 怎样操作dom innerHTML等
                this.attr =attr;
                this.update();//初始化数据
            }
            update(){
                //dom.(innerHTML等) = vue实例下的data[变量名]
                this.el[this.attr] = this.vm.$data[this.exp];
            }
        }
        //实例vue
        var bb=new Vue({
            el:'#app',
            data:{
                inputText:'树下的老大爷的博客'
            }
        });

      

  • 相关阅读:
    JAVA-初步认识-常用对象API(集合框架-Map集合-hashmap存储自定义对象)
    JAVA-初步认识-常用对象API(集合框架-Map集合常见子类对象)
    springMVC:org.springframework.web.servlet.PageNotFound.handleHttpRequestMethodNotSupported Request method 'POST' not supported
    Could not open ServletContext resource [/WEB-INF/applicationContext.xml]解决方法
    org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    struts2在idea中加入json的jar包后,引用无法解析的解决方法
    struts2 切换jar包版本的时候,idea造成jar包重复...导致错误
    struts2没有spring的情况下加了struts2-spring-plugin-2.3.24.1.jar导致错误
    事务配置不对导致:•Could not obtain transaction-synchronized Session for current thread
    idea:ssh整合小例子:读取数据库信息显示到jsp上面
  • 原文地址:https://www.cnblogs.com/sxldy/p/10938139.html
Copyright © 2011-2022 走看看