/* 1.Vue是如何实现实时监听数据变化的? 通过原生JS的 defineProperty 方法 2.defineProperty方法的特点 可以直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象 3.defineProperty用法 obj: 需要操作的对象 prop: 需要操作的属性 descriptor: 属性描述符 Object.defineProperty(obj, prop, descriptor) */ let obj = {}; // 需求: 给obj对象动态新增一个name属性,并且name属性的取值必须是abc Object.defineProperty(obj, 'name', { value: 'abc', writable: true, // true 新增的属性值可修改。默认不可修改 configurable: true, // name属性是否可删除。默认不可删除 enumerable: true, // 新增的name属性是否可迭代遍历。默认不可 }) console.log(obj) // {name: "abc"} // 默认不可删除新增的属性 delete obj.name /* 3.1 defineProperty除了可以动态修改/新增对象的属性以外 还可以在修改/新增的时候给该属性添加get/set方法 3.2 get/set方法特点 只要通过defineProperty给某个属性添加了 get/set方法 那么以后只要获取这个属性的值就会自动调用get,设置了这个属性的值就会自动条用set 3.3注意点 如果设置了get/set方法,那么就不能通过value直接赋值,也不能设置writable: true */ let oldValue = "测试数据"; Object.defineProperty(obj, 'test', { configurable: true, enumerable: true, get() { return oldValue }, set(newValue) { if(oldValue !== newValue) { oldValue = newValue; } } }) // 需求:快速监听对象中所有属性的变化 let obj = { name: 'ceshi', age: 18 } // 只要将需要监听的那个对象传递给Observer这个类 // 这个类就可以快速的给传入的对象的所有属性都添加get/set方法 class Observer { constructor(data) { this.observer(data); // constructor 方法是类的默认方法,创建类的实例化对象时被调用。 } observer(obj) { if(obj && typeof obj === 'object') { // 遍历取出传入对象的所有属性, 给遍历到的属性都增加get/set方法 for(let key in obj) { this.defineRecative(obj, key, obj[key]) } } } // obj: 需要操作的对象 // attr: 需要新增get/set方法的属性 // value: 需要新增get/set方法属性的取值 defineRecative(obj, attr, value) { // 如果属性的取值又是一个对象, 那么也需要给这个对象的所有属性添加get/set方法 this.observer(value); Object.defineProperty(obj, attr, { get(){ return value; }, set:(newValue)=>{ if(value !== newValue){ // 如果给属性赋值的新值又是一个对象, 那么也需要给这个对象的所有属性添加get/set方法 this.observer(newValue); value = newValue; console.log('监听到数据的变化, 需要去更新UI'); } } }) } } new Observer(obj); // obj.name = '123'; // obj.age = 23; // obj.name.a = 'dtdgf'; obj.name = {a: 'abc'}; obj.name.a = '测试文本';