Vue学习笔记(三):Vue数据绑定原理
我们对一个Object对象设置属性时,一般是通过对象的.操作符或者[]操作符直接赋值的,例如obj1.a = 1 或 obj1['a'] = 1,通过这种方式添加的属性后续可以更改属性值,并且默认该属性是可枚举的,即通过for (const key in obj1) 或 obj1.keys()均可访问到属性。如果我们想在新增属性后不允许再更改属性值或者将该属性设置为非枚举属性,那我们该如何处理呢?
这个时候,我们就需要使用静态方法Object.defineProperty进行操作,Object.defineProperty方法可以通过对属性的元数据进行操作,控制属性行为。Object.defineProperty定义如下:
Object.defineProperty(obj, prop, descriptor)
参数
- obj: Object,Required,要在其上定义属性的对象。
- prop: String|Symbol,Required,要定义或修改的属性的名称。
- descriptor: Object,Required,将被定义或修改的属性描述符。
返回值
Object,返回被传递给函数的对象obj。
Object.defineProperty(obj, prop, descriptor)中的参数descriptor就是属性描述符,就是定义属性行为的元数据信息。属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个Boolean类型的元数据属性,值为true或false,用于定义对属性的某种操作行为是允许还是禁止。存取描述符是由getter-setter函数对描述的属性。描述符必须是这两种形式之一,即descriptor要么是数据描述符,要么是存取描述符,不能同时包含数据描述符和存取描述符。
数据描述符和存取描述符均具有以下可选键值:
- configurable: 当且仅当该属性的 configurable 为 true 时,才能够再次修改该属性的属性描述符,同时该属性也能从对应的对象上被删除。默认为 false。
- enumerable: 当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为 false。
- value: 该属性的初始值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
- writable: 当且仅当该属性的writable为true时,该属性才能被写入值。默认为 false。
例如,我们定义一个person对象,后续通过Object.defineProperty方法为person添加一个“age”属性,设置其初始值为18,并设置为可修改,代码如下:
<script type="text/javascript" >
let person = {
name:'张三',
sex:'男',
}
Object.defineProperty(person,'age',{
value:18,
// enumerable:true, //控制属性是否可以枚举,默认值是false
writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true //控制属性是否可以被删除,默认值是false
})
console.log(person)
</script>
通过上述例子,我们可以看出,Object.defineProperty为对象属性增加了可操作性性。不过,这不是关键,关键是,Object.defineProperty中可以定义setter和gettter:
- get: 一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。默认为 undefined。
- set: 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。默认为 undefined。
例如,我们定义一个变量num,并将其值赋值给person中新定义的属性age,最简单的做法就是定义person时,将num赋值给age:
<script type="text/javascript" >
let num = 30
let person = {
name:'张三',
sex:'男',
age: num
}
</script>
但是,这么做只是让num在person定义时,将值赋给age,后续如果num值发生修改,age依然是最初的值,如果要让age值始终与num一致,通过Object.defineProperty可以这么做:
</script>
Object.defineProperty(person,'age',{
// 读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get(){
return num
},
// 修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
num = value
}
})
</script>
如下图片所示,在控制台无论num怎么修改,age属性值依然会跟着变化:
看到这,是不是有些明白了?有点Vue数据绑定的韵味了,是的,这就是Vue数据绑定的基础——数据绑定的原理。
作者:奥辰
微信号:chb1137796095
Github:https://github.com/ChenHuabin321
欢迎加V交流,共同学习,共同进步!
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。