Vue中
$ 开始的属性是供程序员开发使用的
_ 开始的属性是vue 框架底层使用的
可以直接访问data 中的属性
使用数据代理机制实现
数据代理机制: 通过访问代理对象的属性 间接 访问 目标对象的属性
数据代理机制 核心 Object.defineProperty 为对象添加一个属性
Object.defineProperty(obj, prop, descriptor)
obj | 要定义属性的对象 |
prop | 要定义或修改的属性的名称 |
descriptor | 要定义或修改的属性描述符 |
返回值 | 被传递给函数的对象 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入vue,引入之后vue.js 创建了一个全局变量Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id = "app">
<input v-model="msg" />
</div>
<script type="text/javascript">
//创建一个对象
let book = {};
//给 book 对象添加属性
newBook = Object.defineProperty(
//需要添加属性的对象
book,
//要添加的属性 名
"name",
{
//属性的 值
value:"毛选"
}
);
</script>
</body>
</html>
book.name 赋值 无效
writable: true属性可修改,false属性不可修改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入vue,引入之后vue.js 创建了一个全局变量Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id = "app">
<input v-model="msg" />
</div>
<script type="text/javascript">
//创建一个对象
let book = {};
//给 book 对象添加属性
newBook = Object.defineProperty(
//需要添加属性的对象
book,
//要添加的属性 名
"name",
{
//属性的 值
value:"毛选",
//可修改属性的值
writable: true
}
);
</script>
</body>
</html>
getter setter 方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入vue,引入之后vue.js 创建了一个全局变量Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id = "app">
<input v-model="msg" />
</div>
<script type="text/javascript">
//创建一个对象
let book = {};
//给 book 对象添加属性
newBook = Object.defineProperty(
//需要添加属性的对象
book,
//要添加的属性 名
"name",
{
//属性的 值
value:"毛选",
//可修改属性的值
writable: true,
//有get set 配置项时,value writable 配置项不允许使用
//getter方法配置项,在获取添加的这个属性 的值时 该方法会被调用
get:function(){
},
//setter方法配置项,在修改 添加的这个属性的 值时 该方法会被调用
//省略 :function 的简写
set(){
}
}
);
</script>
</body>
</html>
有get set 配置项时,value writable 配置项不允许使用
获取 添加 属性的 值
getter 方法被调用
修改 添加 属性的 值
setter 方法被调用
getter 方法必须有返回值,获取属性值时获取到的就是getter方法的返回值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入vue,引入之后vue.js 创建了一个全局变量Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id = "app">
<input v-model="msg" />
</div>
<script type="text/javascript">
//创建一个对象
let book = {};
//给 book 对象添加属性
newBook = Object.defineProperty(
//需要添加属性的对象
book,
//要添加的属性 名
"name",
{
//getter方法配置项,在获取添加的这个属性 的值时 该方法会被调用
get:function(){
//getter 方法必须有返回值,获取属性值时获取到的就是getter方法的返回值
return "毛选";
},
//setter方法配置项,在修改 添加的这个属性的 值时 该方法会被调用
//省略 :function 的简写
set(){
console.log("setter");
}
}
);
</script>
</body>
</html>
setter方法 参数 接收为属性赋的值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入vue,引入之后vue.js 创建了一个全局变量Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id = "app">
<input v-model="msg" />
</div>
<script type="text/javascript">
//创建一个对象
let book = {};
//给 book 对象添加属性
newBook = Object.defineProperty(
//需要添加属性的对象
book,
//要添加的属性 名
"name",
{
//getter方法配置项,在获取添加的这个属性 的值时 该方法会被调用
get:function(){
//getter 方法必须有返回值,获取属性值时获取到的就是getter方法的返回值
return "毛选";
},
//setter方法配置项,在修改 添加的这个属性的 值时 该方法会被调用
//省略 :function 的简写
//参数 接收 为 属性赋的值
set(value){
console.log("赋值" + value);
}
}
);
</script>
</body>
</html>
book.name 获取属性值时,其实获取的是变量 tmp 的值
book.name="value" 给属性赋值时,其实是为变量tmp赋值
book.name 就代理了 变量 tmp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入vue,引入之后vue.js 创建了一个全局变量Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id = "app">
<input v-model="msg" />
</div>
<script type="text/javascript">
//创建一个对象
let book = {};
let tmp ;
//给 book 对象添加属性
newBook = Object.defineProperty(
//需要添加属性的对象
book,
//要添加的属性 名
"name",
{
//getter方法配置项,在获取添加的这个属性 的值时 该方法会被调用
get:function(){
//getter 方法必须有返回值,获取属性值时获取到的就是getter方法的返回值
return tmp;
},
//setter方法配置项,在修改 添加的这个属性的 值时 该方法会被调用
//省略 :function 的简写
//参数 接收 为 属性赋的值
set(value){
tmp = value;
}
}
);
</script>
</body>
</html>
第一次获取tmp的值,undefined
book.name获取的其实是tmp 的值(调用getter方法),一样为 undefined
book.name="局外人",调用setter方法,为tmp赋值,
再次获取book.name 和 tmp 的值, 为 局外人
数据代理机制的实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入vue,引入之后vue.js 创建了一个全局变量Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id = "app">
<input v-model="msg" />
</div>
<script type="text/javascript">
//目标对象
let target = {
name: "罗小黑"
};
//代理对象
let proxy = {};
//给代理对象新增一个属性
Object.defineProperty(
proxy,
'name',
{
get(){
//间接访问目标对象的属性
return target.name;
},
set(value){
//将值赋给目标对象的属性
target.name = value;
}
}
);
</script>
</body>
</html>
vue 数据代理对属性名的要求
不能以 $ or _ 开始
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入vue,引入之后vue.js 创建了一个全局变量Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id = "app">
</div>
<script type="text/javascript">
const vm = new Vue(
{
el: "#app",
data: {
msg: "msg",
_msg: "_msg",
$msg: "$msg"
}
}
);
</script>
</body>
</html>
vm 对象中只有msg属性,没有_msg,$msg 属性,以$ or _ 开始的属性名 vue 不会做数据代理 $ _ 开始的属性名 是 vue框架 自己要用
模拟 vue 数据代理
//定义一个类
class Vue {
//定义构造函数
constructor(option){
//获取所有的属性名
let propertys = Object.keys(option.data);
//添加代理属性
propertys.forEach(
/* ()=> {} 形式为箭头函数 其内没有this ,会从上一级作用域寻找 this 变量
function(){} 中的this 为调用该方法的对象,此处箭头函数中的this 从上一级作用域找到的 this 是 constructor 创建的对象
*/
(propertyName,index) => {
Object.defineProperty(this,propertyName,{
get(){
return option.data[propertyName];
},
set(val){
option.data[propertyName] = val;
}
});
}
);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入vue,引入之后vue.js 创建了一个全局变量Vue-->
<script type="text/javascript" src="../js/myVue01.js"></script>
</head>
<body>
<div id = "app">
</div>
<script type="text/javascript">
const vm = new Vue(
{
data:{
msg: "my_Vue"
}
}
);
</script>
</body>
</html>