IFE糯米学院-Vue动态数据绑定(一)

实现的样例

let app1 = new Observer({
  name: 'youngwind',
  age: 25
});

let app2 = new Observer({
  university: 'bupt',
  major: 'computer'
});

// 要实现的结果如下:
app1.data.name // 你访问了 name
app.data.age = 100;  // 你设置了 age,新的值为100
app2.data.university // 你访问了 university
app2.data.major = 'science'  // 你设置了 major,新的值为 science

实现要求

  1. 传入参数只考虑对象,不考虑数组。
  2. new Observer返回一个对象,其 data 属性要能够访问到传递进去的对象。
  3. 通过 data 访问属性和设置属性的时候,均能打印出右侧对应的信息。

参考文章

思路

我是完全没有思路的,直到看了参考 ToT

Object.defineProperty(obj, prop, descriptor)阅读

  • obj 要在其上定义属性的对象
  • configurable属性:默认false 属性描述符的类型可能被改变,并且可以从当前对象中删除
  • enumberable属性:默认false 属性可以用for…in枚举
  • writable属性:默认false 该属性可以用赋值运算符修改其值
  • value属性:默认undefined
  • get,set:访问器描述符,默认undefined

    划重点 :一个数据描述符是具有价值,这可能会或可能是不可写的属性。一个访问描述符是一个getter,setter方法对函数描述的属性。描述符必须是这两种类型之一; 它不能两者都。
    也就是说:出现了value,writable就不可以在出现getter,setter 因为具有value是否可以修改是用writable来控制,访问器控制符所做的也是这个工作。

  • 具体的可以阅读MDN,而我们完成监听改变需要的就是自定义setter和getter

// MDN示例代码
function Archiver() {
  var temperature = null;

  Object.defineProperty(this, 'temperature', {
    get: function() {
      console.log('get!');
      return temperature;
    },
    set: function(value) {
      console.log('set!');
      temperature = value;
    }
  });
}

var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;

初级实现,直接传入一个对象

function Observe(data) {
    this.data = data;
    this.map(data)// 遍历这个对象的键值
}
Observe.prototype = {
    constructor : Observe,
    map : function(data) {
        for(key in data){
            this.convert(key,data[key]);
        }
    },
    // 给每一个键,也说是每一个属性都绑定上属于自己的get和set。不知道这样理解对不对
    convert : function(key,value) {
        Object.defineProperty(this.data,key,{
            get : function(){
                console.log('you visited me!');
                return name;
            },
            set : function(value) {
                console.log('you change me!');
                name = value;
            }
        })
    }

}

var app1 = new Observe({// 直接传入一个对象
    name: 'youngwind',
    age: 25
});

app1.data.name; // 实现访问
app1.data.age = 100; // 实现改变

中级绑定,如果传入的是对象内含有对象呢?

首先遍历到最底层的属性值,然后递归调用观察器,这里基本就是照搬参考上的代码了。

function Observe(data) {
    this.data = data;
    this.map(data)
}
Observe.prototype = {
    constructor : Observe,
    map: function(obj) {
        var val;
        for (var key in obj) {
            // for...in 循环会把对象原型链上的所有可枚举属性都循环出来
            // 而我们想要监听的仅仅是这个对象本身拥有的属性,所以要这么做。
            if (obj.hasOwnProperty(key)) {
                val = obj[key];
                // 这里进行判断,如果还没有遍历到最底层,继续new Observer
                if (typeof val === 'object') {
                    new Observe(val);
                }
                // 除了要遍历到最底层,监听最底层的变化,也要监听自己的的变化
                this.convert(key, val);
            }
        }
    },
    convert: function(key,value) {
    // 监听对象变成了this.data
        Object.defineProperty(this.data, key, {
            enumerable: true,// 可以被枚举
            configurable: true,
            get: function() {
                console.log('you visited ' + key);
                return value;
            },
            set: function(newValue) {
                console.log('you change ' + key + ' to ' + newValue);
                if(value == newValue) { return ;}
                value = newValue;
            }
        })
    }
}

var data = {// 传入一个复杂的data,要遍历到他的每一个键值对
    user: {
        name: "hehe",
        age: "24"
    },
    address: {
        city: "beijing"
    }
};
var app1 = new Observe(data);

app1.data.user;
app1.data.user.name; // 实现访问
app1.data.user.age = '100'; // 实现改变

问题

  1. 只监听的对象的变化,没有处理数组的变化。
  2. 当你重新set的属性是对象的话,那么新set的对象里面的属性不能调用getter和setter。比如像下图所示,重新设置的job属性就不在带有自定义的getter和setter了,不再提示“你访问了job”这些字样。

我不是特别懂,所以,需要继续学习才能明白这个问题到底是什么意思,哈哈,这是仅仅是作为一个学习笔记咯,大家还是要去看原文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值