数据代理
Vue框架的特性,主要是体现在如下两方面
- 数据驱动视图
- 双向数据绑定
数据驱动视图
- 好处:当页面数据发生变化时,页面会自动重新渲染!
- 注意:数据驱动视图是单向的数据绑定
双向数据绑定
在网页中,form表单负责**采集数据**,Ajax负责提交数据。
表单负责采集数据,作者在不操作DOM的前题下,vue自动把用户输入的信息取到更新到js数据中
好处:开发者不再需要手动操作DOM元素,来获取表单元素最新的值!
vue的特点
采用主键化模式,提高代码复用率、让代码更好维护 声明式编码,让编码人员无需直接操作dom元素
MVVM模型
- M:模型(Model) : data中的数据
- V:视图(View) :模板代码
- VM:视图模型(ViewModel): Vue实例 观察发现:
- data中所有的属性,最后都出现在vm身上
- vm身是的所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用
Object。defineproperty方法 (数据劫持,数据代理,计算属性)
Object.keys()将对象里的所有属性名提取出来形成数组
Object.defineProperty
- // 参数1:传添加属性的对象
- // 参数2:传对象中新增的键
- // 参数3:传配置项
枚举
可以枚举就是形容能遍历,不能枚举就是不能遍历,在我们使用Object.defineProperty进行添加对象里的键值时,添加的不能枚举
Object.defineProperty中的配置参数
enumerable
enumerable 控制Object.defineProperty创建的键值能否枚举,控制属性是否可以枚举,默认值是false
writerable
writerable 控制Object.defineProperty创建的键值能否修改,控制属性是否可以被修改,默认值是false
configurable
configurable 控制Object.defineProperty创建的属性是否能删除,控制属性是否可以删除,默认值为false
get()
当有人读取obj中age属性时,get函数(getter)就会被调用,且返回值就是age的值
注意:当我们写get()时上面的配置需要注释,否则↓
set()
当有人修改obj中age属性时,set函数(getter)就会被调用,且会收到修改的具体值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let number = 20
let obj = {
name: '靓仔',
gander: "男",
}
// Object.defineProperty
// 参数1:传添加属性的对象
// 参数2:传对象中新增的键
// 参数3:传配置项
Object.defineProperty(obj, "age", {
/* value: 18,//在对象创建的键的值
enumerable: true,//控制属性是否可以枚举,默认值是false
writable: true, //控制属性是否可以被修改,默认值是false
configurable: true, //控制属性是否可以删除,默认值为false */
// 当有人读取obj中age属性时,get函数(getter)就会被调用,且返回值就是age的值
get() {
console.log('有人读取age属性了')
return number
},
// 当有人修改obj中age属性时,set函数(getter)就会被调用,且会收到修改的具体值
set(value) {
console.log('有人修改了age')
number = value
}
})
// 不能枚举是什么呢?就是不能遍历
/* for (let key in obj) {
console.log(obj[key] + "========" + key);
}
console.log(Object.keys(obj)) */
</script>
</body>
</html>
数据代理
let obj1 = { x: 100 }
let obj2 = { y: 200 }
Object.defineProperty(obj2, 'x', {
get() {
console.log("obj2.x被读取将obj.x的值赋值给obj2.x")
return obj1.x
},
set(value) {
console.log("obj2.x被修改导致obj1.x的值为obj2.x被修改的值");
obj1.x = value
}
})
Vue中的数据代理
Vue中的数据代理是怎么样的呢?
在我们创建Vue实例化对象vm时存储在Vue中配置项的data中的数据是存储在vm实例化对象中的_data中
但我们看到在vm实例化对象中也存在
那是为什么呢?
那是为了方便我们引用vm实例化对象中data的数据,因为我们当前的root盒子被vm实例化对象接管了,root盒子中的插值中如果要访问vm实例化对象中的data中的值我们需要_data.name,才能访问到会比较麻烦,所有我们可以看到vm实例化对象中还出现了
由此我们可以看出vm中的name和age被数据代理了,那他们代理的数据是哪里的呢?
很明显代理的肯定是vm实例化对象中_data的数据,vm实例化对象中 _data和Vue配置项中的data数据是等价的。但我们_data中数据打开与我们预想的不一样
这是为什么呢?
因为_data中的数据进行了数据拦截,对于数据拦截我就是与视图相关联数据变化就渲染到视图
只要Vue配置项data中的数据变化视图就会变化
<!--
1.Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:
更加方便的操作data中的数据
3.基本原理
通过Object.DefineProperty()把data对象中所有属性添加到vm上
为每一个添加到vm上的属性,都指定一个getter/setter。
在getter/setter内部去操作(读/写)data中对应的属性
-->
<div id="root">
<div>{{name}}</div>
<div>{{age}}</div>
</div>
<script src="../../vue.js"></script>
<script>
Vue.config.productionTip = false
let vm = new Vue({
el: '#root',
data: {
name: "小黑",
age: 21
}
})
</script>