Vue数据代理
Posted 橘猫吃不胖~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue数据代理相关的知识,希望对你有一定的参考价值。
Vue数据代理
1 Object.defineProperty方法
在Vue中,有很多地方使用到了Object.defineProperty
方法,例如数据劫持、数据代理、计算属性等。Object.defineProperty
方法用来给一个对象添加属性,或者修改一个对象上的属性。它的语法如下:
Object.defineProperty(obj, prop, descriptor)
// obj:要定义属性的对象
// prop:要定义或修改的属性名称或Symbol
// descriptor:要定义或修改的属性描述符
// 返回值:该对象
在默认情况下,使用Object.defineProperty
添加的属性不可以执行枚举、修改等操作,因此需要在descriptor
中添加响应的配置项,配置项具体如下:
配置项 | 描述 |
---|---|
value | 该属性对应的值,可以是任何有效的javascript 值(数值,对象,函数等),默认为undefined |
enumerable | 表示该属性是否可以枚举,true为可枚举,默认为false不可枚举 |
writable | 控制属性是否可以被修改,true为可以修改,默认为false |
configurable | 控制属性是否可以被删除,true为可以被删除,默认为false |
get() | 属性的getter函数,当访问该属性时,会调用此函数,该函数的返回值会被用作属性的值 |
set() | 属性的setter函数,当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),默认为undefined |
示例:使用Object.defineProperty()
方法为person
对象添加一个新属性
let person = ;
Object.defineProperty(person, "name",
value: "橘猫吃不胖", // name属性值为橘猫吃不胖
enumerable: true, // 属性可以枚举
)
console.log(person) // name: '橘猫吃不胖'
person.name = "张三"; // 修改name属性值为张三,结果不能修改
console.log(person) // name: '橘猫吃不胖'
delete person.name; // 删除该属性,结果不能删除
console.log(person) // name: '橘猫吃不胖'
由上面代码可知,无法修改和删除name
属性,因此为其再添加配置项writable
(是否可以被修改)和configurable
(是否可以被删除),就可以执行修改和删除的操作了,代码如下:
let person = ;
Object.defineProperty(person, "name",
value: "橘猫吃不胖", // name属性值为橘猫吃不胖
enumerable: true, // 属性可以枚举
writable: true, // 属性可以被修改
configurable: true, // 属性可以被删除
)
console.log(person); // name: '橘猫吃不胖'
person.name = "张三";
console.log(person); // name: '张三'
delete person.name;
console.log(person); //
示例:自定义setter和getter
let person = ;
let str = "橘猫吃不胖";
Object.defineProperty(person, "name",
get() // 返回一个字符串
return str;
,
set(value)
str = value; // 将字符串的值改为最新的值
)
console.log(person.name); // 橘猫吃不胖
person.name = "张三";
console.log(person.name); // 张三
2 什么是数据代理
数据代理就是通过一个对象代理对另一个对象中属性的操作(读/写)。
比如说,有两个对象obj1和obj2,其中obj1中有一个属性x,但是在obj2中可以读取和修改obj1中的属性x,这样就达到了一个数据代理的效果,代码如下:
let obj1 = x: 100 ;
let obj2 = y: 200 ;
// 通过Object.defineProperty()方法为obj2添加属性x
Object.defineProperty(obj2, "x",
get() // 读取时返回obj1的x值
return obj1.x;
,
set(value) // 修改时更改obj1的x值
obj1.x = value;
)
以上代码就是最简单的一个数据代理,我们可以通过obj2访问并修改obj1中的x的值,示例如下:
console.log(obj2.x); // 100
console.log(obj1.x); // 100
obj2.x = 150; // 通过obj2修改x的值为150
console.log(obj2.x); // 150
console.log(obj1.x); // 150
3 Vue中的数据代理
下面一段代码中,我们在data
中定义了name
和age
,然后在页面上使用双大括号进行了数据显示。其中,Vue实例
vm
的身上会出现name
和age
两个属性。
<div id="app">
<h3>姓名:name</h3>
<h3>年龄:age</h3>
</div>
<script>
var vm = new Vue(
el: "#app",
data:
name: "橘猫吃不胖",
age: "2岁"
)
</script>
我们在控制台输出一下vm
实例,可以看到name
和age
两个属性,当我们将鼠标悬停在(...)
上时,显示了Invoke property getter
。通过对Object.defineProperty()
方法的了解,我们可以知道name
和age
两个属性都是通过Object.defineProperty()
方法添加上来的。
当访问name
时,是getter在工作,当修改name
时,是setter在工作,因此,在vm
中,我们也可以看到它们的getter和setter方法。
那么我们通过vm
读取与修改name
都是通过读取与修改data
中的name
,这就是一个数据代理。
接下来可以对我们刚才的结论进行验证。
验证getter方法
验证思路如下:当我们修改data
中的name
时,vm
中的name
也会进行一个修改。首先在控制台读取当前的name
值vm.name
,我们通过vm
来获得name
,那么getter会将data
中的name
返回给vm
。
那么接下来我们将data
中的name
修改为张三,然后再来访问vm
中的name
,发现这时name
变成了张三,此时我们就验证了getter方法。
<div id="app">
<h3>姓名:name</h3>
<h3>年龄:age</h3>
</div>
<script>
var vm = new Vue(
el: "#app",
data:
name: "张三", // name修改为张三
age: "2岁"
)
</script>
验证setter方法
在上面代码中我们将name
修改为了张三,那么我们在控制台修改vm.name
为橘猫吃不胖,这时会将data
中的name
修改为橘猫吃不胖。这个变化我们并不能通过我们的代码看出来,也不能通过普通的data.name
拿到data
中name
的值,因此我们需要通过其他的途径拿到data
的值。
这时我们发现,Vue实例vm
中的_data
属性帮我们存储了data
的值,下面我们先对这个进行一个简单的验证。
思路如下,在代码中将data
在外部定义,通过验证vm._data === options.data === data
来验证我们的想法,其中options
就是new Vue()
中大括号内的配置项,这时
options.data
就是我们在外部定义的data
,具体代码如下:
<div id="app">
<h3>姓名:name</h3>
<h3>年龄:age</h3>
</div>
<script>
let data =
name: "张三",
age: "2岁"
var vm = new Vue(
el: "#app",
data
)
</script>
这时我们就验证了vm._data
就是在Vue配置项中的data
。回到我们之前通过vm.name
将张三修改为橘猫吃不胖,那么我们可以通过观察vm._data.name
是否被修改来验证setter方法,从结果可以看到,答案是正确的。
因此,当我们使用vm.name = "橘猫吃不胖"
来将name
从张三修改为橘猫吃不胖时,那么就会通过setter方法将data
进行一个修改。
以上是关于Vue数据代理的主要内容,如果未能解决你的问题,请参考以下文章