引入数据代理的概念
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>引入数据代理的概念</title>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<script type="text/javascript">
// 这个变量提供给其他用
let number = 29;
let person = {
'name':'胡杨'
,'sex':'男'
// 虽然在这里引用了数据number,但是仅限于在程序初始化的时候,如果number再变,age就不会随着改变
,'age':number
};
console.log(person);
</script>
</body>
</html>
虽然在这里,age引用了变量number的值,但是也仅限于在代码初始化的时候,一旦程序执行结束之后,age的值就是29,而当number数值变了之后,age不会随之改变。
那么如何让age属性的值,随着number的改变而改变呢?
答案是:不要一开始就获取age的值,而是在需要的时候,而且是每次使用的时候都再获取一次,这样就可以在跟number就行关联,每当number的值改变的时候,因为每次调用age都会重新获取一次number的值,就可以让age的值随着number的值的变化而变化,在这里有个关键的点就是需要一个方法,用于每次获取调用,这个方法就是getter,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>引入数据代理的概念</title>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<script type="text/javascript">
// 这个变量提供给其他用
let number = 29;
let person = {
'name':'胡杨'
,'sex':'男'
// 虽然在这里引用了数据number,但是仅限于在程序初始化的时候,如果number再变,age就不会随着改变
// ,'age':number
};
Object.defineProperty(
person
,'age'
,{
// // 这个get函数什么时候会被调用呢?当有人调用person的age属性的时候,get函数(getter)就会被调用,且返回值就是age的值
// get:function(){
// console.log('有人读取age属性了');
// return number;
// }
// 可以简写成如下的形式
get(){
console.log('有人读取age属性了');
return number;
}
})
console.log(person);
</script>
</body>
</html>
当输出person对象的时候,并不是一开始就有age的值,而是在点击小括号里省略号的时候,才获取age的值并目是通过getter方法去获取。
添加的输出语句,在getter方法每次被调用的时候就会打印输出。
当我们修改number的值,age的属性值也会随之改变。
可以与java在创建类的时候有异曲同工之处,Object.defineProperty就是相当于java在定义一个类的时候,创建一个属性age,然后再给age属性定义一个getter方法;java的实例在调用被private修饰的的age属性时,只能通过getter方法去调用,只不过在这里js可以直接通过person.age的方式去调用;而age属性是通过Object.defineProperty方式定义的,这样person在调用age属性的时候,如果配置了getter函数,则会通过调用getter函数来获取age的值,getter函数的return返回值,就是age属性的值。
那么有getter就有setter
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>引入数据代理的概念</title>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<script type="text/javascript">
// 这个变量提供给其他用
let number = 29;
let person = {
'name':'胡杨'
,'sex':'男'
// 虽然在这里引用了数据number,但是仅限于在程序初始化的时候,如果number再变,age就不会随着改变
// ,'age':number
};
Object.defineProperty(
person
,'age'
,{
// // 这个get函数什么时候会被调用呢?当有人调用person的age属性的时候,get函数(getter)就会被调用,且返回值就是age的值
// get:function(){
// console.log('有人读取age属性了');
// return number;
// }
// 可以简写成如下的形式
get(){
console.log('有人读取age属性了');
return number;
}
// 当有人修改age属性值的时候,set函数(setter)就会被调用
,set(value){
console.log('有人修改了age的值,age的值为',value);
number = value;
}
})
console.log(person);
</script>
</body>
</html>
setter函数在使用的时候,只需要通过person.age = 99这种方式即可,会将99这个值传递给setter函数,在setter函数内完成业务处理;如此就可以实现,给person这个实例对象的age属性实现修改和获取。
数据代理定义
通过一个对象代理另一个对象中属性的操作(包括读、写)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>什么是数据代理</title>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<script type="text/javascript">
let obj1 = {
x:100
};
let obj2 = {
y:200
};
Object.defineProperty(obj2, 'x', {
get(){
return obj1.x;
}
,set(value){
obj1.x = value;
}
})
</script>
</body>
</html>
Vue中的数据代理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue中的数据代理</title>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<div id="box">
<ul>
<!--插值语法的使用-->
<li>{{name}}</li>
<li>{{country}}</li>
</ul>
</div>
<script type="text/javascript">
// 关闭浏览器控制台开发环境提示
Vue.config.productionTip = false;
const vm = new Vue({
el:'#box',
data:{
'name':'钟南山',
'country':'中国',
}
});
</script>
</body>
</html>
name和country这两个属性就不是一开始就有,而是要用的时候,再去获取,跟我们之前说的通过Object.defineProperty定义的属性很像,其实vue底层也是使用这种方式实现的数据代理。
需要验证两条线,如下:
- vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)。
- vue数据代理的好处:更加方便的操作data中的数据。
- 基本原理:
-
- 通过Object.defineProperty把data对象中所有属性添加到vm上。
- 为每一个添加到vm上的属性,都指定一个getter和setter。
- 在getter/setter内部去操作(读/写)data中对应的属性。