vue--响应式原理(2)

在谈 Vue 响应式原理之前,我们需要先了解一下 ES5 的 Object 的一个属性 defineProperty。
下面我们来看一段官方的介绍
The Object.defineProperty() method defines a new property directly on an object, or modifies an existing property on an object, and returns the object.
直接在一个对象上定义一个新的属性,或修改一个已经存在的属性。这个方法会返回该对象。
语法:
Object.defineProperty(obj, prop, descriptor)
参数说明:
@params obj // 目标对象 type: Obejct @params prop // 需要定义的属性 type: String @params descriptor // 定义的属性所拥有的特性 type: Obejct
通过简单的介绍可以看看到,也就是定义了个对象的某个属性,但是其中的奥秘主要在第三个参数 descriptor。 我们看一下第三个参数可以设置的属性:
  • value
  • writable
  • get ,set
  • configurable
  • enumerable
分别介绍一下每个属性:
 
1. value
属性的值, 默认为undefined。例如:
var someOne = {}
Object.defineProperty(someOne, 'name', {
    value : 'cover'
})
someOne.name // cover
从表面上看, 貌似和下面的语法是等价的:
someOne.name = 'cover'
那我们继续往下看接下来的属性。
 
2. writable
该属性是否可写, 如果设置成 false,则任何对该属性改写的操作都无效(但不会报错),默认为 false。
var someOne = { };
Object.defineProperty(someOne, "name", {
    value:"coverguo" , // 由于设定了writable属性为false 导致这个量不可以修改
    writable: false 
});  
console.log(someOne.name); // 输出 coverguo
someOne.name = "monkeyWang";
console.log(someOne.name); // 输出coverguo
 
3. configurable
如果为 false,则任何尝试删除目标属性或修改属性以下特性(writable, configurable, enumerable)的行为将被无效化,默认为 false。
var someOne = { };
Object.defineProperty(someOne, "name", {
    configurable: false, // 由于设定了configurable属性为false导致所有属性不可修改
    value: "hello"
});  
// 下面的操作想让 configurable 变为 true 但是不会被允许
Object.defineProperty(someOne, "name", {
    configurable: true,
    value: "hello"
});  // Cannot redefine property: name


var someOne = { };
Object.defineProperty(someOne, "name", {
   configurable: true, // 由于设定了configurable属性为false导致所有属性不可修改
    value: "hello"
});  
// 下面的操作想让 configurable 变为 false 是可以的
Object.defineProperty(someOne, "name", {
   configurable: false,
    value: "hello"
});  
 
4. enumerable
是否能在for...in循环中遍历出来或在Object.keys中列举出来。默认为 false。
var someOne = {}
Object.defineProperty(someOne,"name",{
  value:3445,
  enumerable:true
})
console.log(Object.keys(someOne));// 打印["name"]

改为false

var someOne = {}
Object.defineProperty(someOne,"name",{
  value:3445,
  enumerable:false //注意咯这里改了
})
console.log(Object.keys(someOne));// 打印[]
for...in 类似,不赘述了。
接下来看看更加关键的几个属性:set 和 get
 
5. set 和 get
在 descriptor 中不能同时设置访问器(get 和 set)和 wriable 或 value,否则会错,就是说想用 get 和 set,就不能用 writable 或 value 中的任何一个。
set 和 get,他俩干啥用的的。
var someOne= {}
Object.defineProperty(someOne,"name",{
    set: function (newValue) {
      console.log('你设置了name,新的值是' + newValue);
    },
    get: function (value) {
      console.log('你访问了name');
    }
})
someOne.name = 'monkeyWang'// 你设置了name,新值是monkeyWang
console.log(someOne.name)    // 你访问了name
简单来说,这个 “b” 赋值或者取值的时候会分别触发 set 和 get 对应的函数。
 
演习:
了解了上面这么多,那我们便可以开始 Vue 的基本响应式之旅了:我们从最简单的开始。其中,动态数据绑定就是 Vue 最为基础,最为有用的一个功能。这个系列将分成5部分,一步一步来理解和实现这一功能。ok,我们从最简单的开始。给定任意一个对象,如何监听其属性的读取与变化?也就是说,如何知道程序访问了对象的哪个属性,又改变了哪个属性?
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 
感兴趣的小伙伴可以动手去实现这样一个简单的数据绑定。
 
如果传入参数对象是一个“比较深”的对象(也就是其属性值也可能是对象),那该怎么办呢?考虑传递回调函数。
在实际应用中,当特定数据发生改变的时候,我们是希望做一些特定的事情的,而不是每一次都只能打印出一些信息。所以,我们如何支持传入回调函数的功能?
 

原文地址:https://www.cnblogs.com/absoluteli/p/14082463.html