精华内容
下载资源
问答
  • vue 动态数据绑定

    2019-09-27 10:50:05
    动态数据绑定(一) 我的github iSAM2016 实现的步骤: 1.监听对象属性的读取与变化 Object.defineProperty() 方法会直接在对象上定义一个新的的属性,或者已经存在的属性 并且返回这个属性 语法是 Object....

    动态数据绑定(一)

    我的github iSAM2016

    实现的步骤:

    1.监听对象属性的读取与变化

    Object.defineProperty() 方法会直接在对象上定义一个新的的属性,或者已经存在的属性
    并且返回这个属性

    语法是 Object.defineProperty(obj, prop, descript)
    obj: 目标对象
    prop: 需要定义或修改的属性的名字
    descript: 将被定义或修改的属性的描述符

    描述:

    这个方法精确添加或修改对象的属性,我们添加的属性是可以枚举的属性(Object.keys()/ for...in)

    对象里面存在是属性描述存在的形式是:
    数据描述符:拥有可写入或不可以写入的属性(相当于口令密码)
    存取描述符:由一对getter-setter 函数功能来描述的属性(方法)

    注意:**描述符**必须是两种形式之一,不能同时是两者。

    数据描述符和存取描述符具有以下可选键值:

    1. configurable:当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,也能够被删除。默认为 false
    2. enumerable:当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false

    数据描述符:

    1. value:该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
    2. writable:当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false。

    存取描述符同时具有以下可选键值:

    1. get:一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。
    2. set:一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。

    示例:

    创建属性
    var  o = {};
    Object.defineProperty(o, "a", {value : 37,
                                   writable : true,
                                   enumerable : true,
                                   configurable : true});
    
    console.log(o.a);
    Object.defineProperty(o, "b", {get : function(){ /*console.log( bValue)*/  return value },
                                   set : function(newValue){ bValue = newValue; },
                                   enumerable : true,
                                   configurable : true});
    o.b = 38;
    修改属性
    当属性特性(property attribute) writable 设置为false时,表示 non-writable,属性不能被修改。
    
    var o = {}; // 创建一个新对象
    
    Object.defineProperty(o, "a", { value : 37,
                                    writable : false });
    
    console.log(o.a); // 打印 37
    o.a = 25; // 没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值)
    console.log(o.a); // 打印 37, 赋值不起作用。
    一般的setter 和 getters
    var pattern = {
        get: function () {
            return 'I alway return this string,whatever you have assigned';
        },
        set: function () {
            this.myname = 'this is my name string';
        }
    };
    function TestDefineSetAndGet() {
        Object.defineProperty(this, 'myproperty', pattern);
    }
    var instance = new TestDefineSetAndGet();
    instance.myproperty = 'test';
    
    // 'I alway return this string,whatever you have assigned'
    console.log(instance.myproperty);
    // 'this is my name string'
    console.log(instance.myname);
    解题
    function Observer(property) {
        this.data = {};
        this.recursion(data);
    }
    
    Observer.prototype.recursion = function(obj) {
        var val = null;
        for (key in obj) {
            if(obj.hasOwnProperty(key)) {
                val = obj[val];
                if(typeof val === 'object' && !!val) {
                    new Observer(val);
                }
                this.access(key, val);
            }
        }
    }
    
    Observer.prototype.access = function(key, val) {
        Object.defineProperty(this.data, key, {
            enumerable: true,
            configurable: true,
            get: function () {
                console.log('你访问了' + key);
                return val
            },
            set: function (newVal) {
                console.log('你设置了' + key);
                console.log('新的' + key + ' = ' + newVal)
                if (newVal === val) return;
                val = newVal
            }
        })
    }
    
    
    let app1 = new Observer({
      name: 'youngwind',
      age: 25
    });
    let app2 = new Observer({
      university: 'bupt',
      major: 'computer'
    });
    
    // 要实现的结果如下:
    app1.data.name // 你访问了 name
    app1.data.age = 100;  // 你设置了 age,新的值为100
    app2.data.university // 你访问了 university
    app2.data.major = 'science'  // 你设置了 major,新的值为 science
    多层级对象
    当传入的对象是
    let app1 = new Observer({
       user: {
            name: "liangshaofeng",
            age: "24"
        },
        address: {
            city: "beijing"
        }
    });

    递归解决问题!!

    function Observer(data) {
        this.data = data;
        this.recursion(this.data);
    }
    
    Observer.prototype.recursion = function(obj) {
        var val = null;
        for (key in obj) {
            if(obj.hasOwnProperty(key)) {
                val = obj[key];
                if(typeof val === 'object' && !!val) {
                    new Observer(val);
                }
                this.access(key, val);
            }
        }
    }
    
    Observer.prototype.access = function(key, val) {
        Object.defineProperty(this.data, key, {
            enumerable: true,
            configurable: true,
            get: function () {
                console.log('你访问了' + key);
                return val
            },
            set: function (newVal) {
                console.log('你设置了' + key);
                console.log('新的' + key + ' = ' + newVal)
                if (newVal === val) return;
                val = newVal
            }
        })
    }
    
    let app1 = new Observer({
       user: {
            name: "liangshaofeng",
            age: "24"
        },
         address: {
            city: "beijing"
        }
    });
    
    
    app1.data.user.name // 你访问了 name
    app1.data.user.age = 100;  // 你设置了 age,新的值为100

    增加事件系统

    // 事件系统
    function Event() {
        this.events = {};
    }
    
    Event.prototype.emit = function(attr, val, newVal) {
        this.events[attr] && this.events[attr].forEach(function(item){
            item(val, newVal)
        })
    }
    
    Event.prototype.on = function(attr, callback){
      if(this.events[attr]){
        this.events[attr].push(callback);
      }else{
        this.events[attr] = [callback];
      }
    }
    
    
    
    function Observer(data) {
        this.data = data;
        this.recursion(this.data);
        this.eventsBus  = new Event();
    }
    
    Observer.prototype.recursion = function(obj) {
        var val = null;
        for (key in obj) {
            if(obj.hasOwnProperty(key)) {
                val = obj[key];
                if(typeof val === 'object' && !!val) {
                    new Observer(val);
                }
                this.access(key, val);
            }
        }
    }
    
    Observer.prototype.access = function(key, val) {
        var self = this;
        Object.defineProperty(this.data, key, {
            enumerable: true,
            configurable: true,
            get: function () {
                console.log('你访问了' + key);
                return val
            },
            set: function (newVal) {
                if (typeof newVal === 'object' && !!newVal) {
                    new Observer(newVal);
                }
                console.log('你设置了' + key);
                console.log('新的' + key + ' = ' + newVal)
                self.eventsBus.emit(key, val, newVal);
                if (newVal === val) return;
                val = newVal
            }
        })
    }
    Observer.prototype.$watch = function(attr, callback){
      this.eventsBus.on(attr, callback);
    }
    
    let app1 = new Observer({
       user: {
            name: "liangshaofeng",
            age: "24"
        },
         address: {
            city: "beijing"
        }
    });
    
    
    app1.data.user.name // 你访问了 name
    app1.data.user.age = 100;  // 你设置了 age,新的值为100
    
    app1.data.user.name = {
        lastName: 'liang',
        firstName: 'shaofeng'
     };
     app1.data.user.name.lastName;
     // 这里还需要输出 '你访问了 lastName '
     app1.data.user.name.firstName = 'lalala';
     // 这里还需要输出 '你设置了firstName, 新的值为 lalala'
     var app1 = new Observer({
        name: 'liujianhuan',
        age: 25,
        company: 'Qihoo 360',
        address: 'Chaoyang, Beijing'
    })
    
    app1.$watch('age', function(oldVal, newVal){
        console.log(`我的年龄变了,原来是: ${oldVal}岁,现在是:${newVal}岁了`)
    })
    
    app1.$watch('age', function(oldVal, newVal){
        console.log(`我的年龄真的变了诶,竟然年轻了${oldVal - newVal}岁`)
    })
    
    app1.data.age = 20;

    转载于:https://www.cnblogs.com/iSAM2016/p/6490166.html

    展开全文
  • vue动态数据绑定prop

    2020-08-05 16:56:58
    vue动态数据绑定props思维导读图代码效果 思维导读图 代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript...

    vue动态数据绑定prop

    思维导读图

    在这里插入图片描述

    代码

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title></title>
    		<script type="text/javascript" src="js/vue.js"></script>
    		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    	</head>
    	<body>
    		<div id="add">
    			<ss v-for="e in ell" :tobu="e"></ss>
    		</div>
    	</body>
    	<script type="text/javascript">
    		Vue.component("ss",{
    			props:["tobu"],
    			template:"<p>{{tobu.name}}<p>"
    		})
    		new Vue({
    			el:"#add",
    			data:{
    				ell:[
    					{name:"ssss"},
    					{name:"ssss"},
    					{name:"ssss"},
    					{name:"ssss"},
    					]
    			}
    		})
    	</script>
    </html>
    

    效果

    在这里插入图片描述

    展开全文
  • IFE Vue动态数据绑定

    2017-04-01 11:34:21
    终于完成了Vue动态数据绑定这个任务,发现自己连渣都称不上,沫沫而已。。 提交地址:https://github.com/touming123/IFE-Baidu/tree/master/vue1.给定任意一个对象,如何监听其属性的读取与变化ES中有两种属性:...

    终于完成了Vue动态数据绑定这个任务,发现自己连渣都称不上,沫沫而已。。
    提交地址:https://github.com/touming123/IFE-Baidu/tree/master/vue

    1.给定任意一个对象,如何监听其属性的读取与变化

    ES中有两种属性:数据属性和访问器属性
    数据属性:configurable,enumerable,writabel,value
    访问器属性:(包含一对getter和setter)configurable, enumerable, get, set
    修改属性默认特性:
    Object.defineProperty(属性所在对象,属性名字,描述符)
    现在,我们来修改读取函数:

    Object.defineProperty(this.data, key, {
        enumerable: true,
        configurable: true,
        get: function(){
            console.log(`你访问了${key}`);
            return val;
        },
        set: function(newVal){
            console.log(`你设置${key}为${newVal}`);
            val = newVal;
        }
    })

    2. 继续

    新设置的对象的属性如果是对象,是否能继续响应 getter 和 setter

    在set的时候,判断newVal, 如果是一个对象则继续相应getter、setter

        Object.defineProperty(this.data, key, {
            enumerable: true,
            configurable: true,
    
            get: function () {
                console.log('你访问了' + key);
                return val;
            },
    
            set: function (newVal) {
                console.log('你设置了' + key);
                console.log('新的' + key + '=' + newVal);
                val = newVal;
                //设置新的值是一个对象,继续响应getter和setter
                if (typeof newVal === 'object') {
                    new Observer(val);
                }
            }
    })

    实现$wathc(),当特定数据发生改变的时候,做一些特定的事情的

    利用观察者模式(https://juejin.im/entry/580b5553570c350068e6c2d6
    为Observer添加事件队列
    添加$watch方法,订阅事件
    当set时触发事件执行

    function Event() {
        this.events = {};
    }
    
    Event.prototype.on = function(attr, callback) {
        if (this.events[attr]) {
            this.events[attr].push(callback);
        } else {
            this.events[attr] = [callback];
        }
    }
    
    Event.prototype.off = function(attr) {
        for (let key in this.events) {
            if (this.events.hasOwnProperty(key) && key === attr) {
                delete this.events[key];
            }
        }
    }
    
    Event.prototype.emit = function (attr, ...args) {
        this.events[attr] && this.events[attr].forEach(item => {
            item(...args);
        });
    }

    3.事件向上传播

    Observer观察对象属性变化
    Dep订阅收集器
    Watcher订阅事件

    TO-DO-More

    4.静态数据绑定

    class Vue{
        constructor(options) {
            this.$el = document.querySelector(options.el);
            this.$data = options.data;
            this.map = new Map();
            this.render()
         }
    }

    this.$el得到DOM节点
    render()计算属性值

        render() {
            let self = this,
                inner = self.$el.innerHTML,
                reg = /.*({{(.*)?}})/g,
                result = null,
                origin = inner;
            while(result = reg.exec(origin)) {
                let str = result[1],
                key = result[2].trim(),
                value = '';
                if (self.map.has(key)) {
                    value = self.map.get(key);
                } else {
                    value = self.getValue(key, self.$data);
                    self.map.set(key, value);
                }
                inner = inner.replace(str, value);
            }
            self.$el.innerHTML = inner;
    }

    正则表达式的强大,沫沫需要继续学习(http://deerchao.net/tutorials/regex/regex.htm

    5. 动态数据绑定

    class Vue{
        constructor(options) {
            this.$el = document.querySelector(options.el);
            this.$data = options.data;
            this._observer = new Observer(this);
            this._observer.$watch('$data', this.render.bind(this));
            this._originHtml = this.$el.innerHTML;
            this.render();
        }
    }

    添加Observer,订阅$data,变化时执行render

    展开全文
  • 基于vue动态数据绑定2,再多考虑一个问题:”深层次数据变化如何逐层往上传播”。举个例子。let app = new Observer({ name: { first: 'yy', last: 'jm' }, age: 18 });app2.$watch('name', function (newName)...

    基于vue动态数据绑定2,再多考虑一个问题:”深层次数据变化如何逐层往上传播”。举个例子。

    let app = new Observer({
        name: {
            first: 'yy',
            last: 'jm'
        },
        age: 18
    });
    
    app2.$watch('name', function (newName) {
        console.log('你的姓名发生了变化')
    });
    
    app.data.name.firstName = 'hahaha';
    // 输出:你的姓名发生了变化。
    

    为了实现深层次数据变化的向上传播,需要得到被改变的数据的父级并触发相应的回调函数,然后再逐级向上触发每一层级的回调函数。实现代码如下:

    <script>
    function Observer(data, events, parent, parentKey){
        this.data = data;
        this.events = events || {};
        this.parent = parent || {};
        this.parentKey = parentKey || '';
        this.walk(data, this.events);
    }
    Observer.prototype.walk = function(data, events) {
        for(var key in data) {
            if(data.hasOwnProperty(key)){
                if(typeof(data[key]) == 'object'){
                    new Observer(data[key], events, this, key)
                };
                this.convert(key, data[key], events);
            }
        }
    }
    Observer.prototype.convert = function(key, val, events) {
        var self = this;
        Object.defineProperty(this.data, key, {
            enumerable: true,
            configurable: true,
            get: function() {
                console.log('你访问了' + key);
                return val;
            },
            set: function(newVal) {
                console.log('你设置了', key, ',新的值为', newVal);
                if (newVal !== val) {
                    val = newVal;
                    // 保存key的上级,如果有的话
                    var parent = self.parent;
                    // 保存key的上级的key值
                    var parentKey = self.parentKey;
                    // 循环寻找上级触发事件
                    while (parent) {
                      self.$emit(parentKey, newVal);
                      parentKey = parent.parentKey;
                      parent = parent.parent;
                    }
                    //触发当前key事件
                    self.$emit(key, newVal); 
                }
                // 如果这个newVal是obj,继续递归调用new Observer
                if (typeof newVal === "object") {
                    return new Observer(newVal, events, this, key);
                }
            }
        })
    }
    
    Observer.prototype.$watch = function(key, listener) {
        if(!this.events[key]){
            this.events[key] = [];
        };
        this.events[key].push(listener);
    }
    
    Observer.prototype.$emit = function() {
        var key = [].shift.call(arguments);
        var data = [].slice.call(arguments);
        if(!this.events[key] || this.events[key].length < 1) return;
        this.events[key].forEach(function(listener){
            listener(data || {})
        })
    }
    var data = {
        user: {
            name: {
                first: {
                    y: "y"
                },
                last: "jm"
            },
            age: 18
        },
        address: "成都"
    }
    
    let app = new Observer(data);
    
    app.$watch('user', function() {
        console.log('你改变了user');
    });
    app.$watch('name', function(){
        console.log('你改变了name');
    });
    app.$watch('first', function(){
        console.log('你改变了first');
    });
    app.$watch('y', function(y){
        console.log(`你改变了y, 现在是${y}`);
    });
    app.$watch('age', function(age){
        console.log(`你的age改变了,现在是${age}`);
    });
    app.$watch('address', function(address){
        console.log(`你的address改变了,现在是${address}`);
    });
    app.data.user.age = 20;
    </script>

    在vue数据绑定2的基础上,增加了this.parent、提示。parentKey用于得到相应元素的上级,然后再得到上级的上级… 。
    效果如下:
    image

    展开全文
  • 引言 我之前经常使用 Vue,后来不满足于仅仅使用它,我想了解其内部实现原理,所以就尝试学习其...基本上 MVVM 数据双向绑定的框架大都采用了大量的 Object.defineProperty 来实现。 Object.defineProperty 语法 O...
  • 动态数据绑定的三个难点: 对象深度问题 设置新对象是否能够继续响应getter 和 setter 考虑传递回调函数 本文的目的 在实践中使用递归思想 了解设计模式中的“发布-订阅模式” 三大难点 如果传入参数对象是一个...
  • vue动态数据绑定2---响应数据变化

    千次阅读 2017-08-01 20:00:50
    动态数据绑定1的基础上,考虑传递回调函数。在实际应用中,当特定数据发生改变的时候,我们是希望做一些特定的事情的,而不是每一次都只能打印出一些信息。所以,我们需要支持传入回调函数的功能。举个例子。let app...
  • 我们需要有一个对象,将DOM节点和对应的数据一一映射起来。 以此来达到修改DOM相关的任意一个属性的时候,只修改它所对应的节点。而不是去渲染更新整个DOM。 &lt;p&gt;姓名:{{name}},年龄:{{age}}&...
  • 动态数据绑定就是 Vue 最为基础,最为有用的一个功能。从最简单的开始。给定任意一个对象,如何监听其属性的读取与变化?也就是说,如何知道程序访问了对象的哪个属性,又改变了哪个属性? (function(){ window....
  • - 动态数据绑定就是 Vue 最为基础,最为有用的一个功能。给定任意一个对象,如何监听其属性的读取与变化?也就是说,如何知道程序访问了对象的哪个属性,又改变了哪个属性? 举个例子。let app1 = new Observer({ ...
  • 划重点 :一个数据描述符是具有价值,这可能会或可能是不可写的属性。一个访问描述符是一个getter,setter方法对函数描述的属性。描述符必须是这两种类型之一; 它不能两者都。 也就是说:出现了value,writable就...
  • 回调中如何实现冒泡? /* 通过将记录每个属性的父级,当属性值变化,逐级寻找回调 最开始,打算在data上附加父级信息,后来感觉头快爆炸了,实现太麻烦,无法通过属性来获取父级对象名字, 最后想到元素的parentNode , 不...
  • 2.数据改变时,需要回调函数 通过原型上建立一个watchArr对象,保存监听属性和回调函数,在set触发时执行 (function(){ window.Observer = function(data){ this.data=data; this.makeObserver(); }; //监听...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,544
精华内容 617
关键字:

vue动态数据绑定

vue 订阅