Object.defineProperty
let gender = '男';
let obj = {
name: '野原新之助',
age: 6
}
Object.defineProperty(obj, 'gender', {
//默认不可枚举,要想可以枚举,就可以加enumerable: true
//默认不可修改,要想可以修改,就可以加writable: true
//默认不可删除,要想可以删除,就可以加configurable: true
//当读取gender的值的时候,get函数(getter)会被调用,返回age的值
get(){
return gender;
},
//当修改gender的值的时候,set函数(setter)会被调用,更改age的值
//采用这种方法的话可以实现gender与相应值的动态绑定
set(value) {
gender = value
}
})
console.log(obj); //加了一个属性---gender: 男

先修改gen的值就可以发现obj的gender值也被修改了。
注意:如果是直接在对象设置值的话,将无法实现拓展功能,如不能被枚举、写等,以及无法实现动态绑定。而用该Object方法的话,相当于对象与变量之间的桥梁,从而能动态绑定。
简单的数据代理
let obj1 = {x: 100};
let obj2 = {y: 200};
Object.defineProperty(obj2,'x',{
get(){
//get的值来自于obj1中的x
return obj1.x;
},
set(value) {
//修改的时候将obj1中的x修改即可
obj1.x = value;
}
})

Vue中的数据代理


1.至于数据的动态变换涉及到之前的动态变化(data值一改变,就会在页面上呈现出来)。
2.为了实现响应式,将_data的内容做了一些改变。

Vue检测数据的原理
对象
Vue是怎么检测到data的内容的改变呢,其实根本原因就是会给包括对象的内容加相应的getter和setter。(因此不可以直接将数组内的对象进行赋值,会检测不到)
部分底层原理:
<script type="text/javascript">
let data ={
name:'野原新之助',
age:'6岁'
}
//接受相应的对象
const obs = new Observer(data);
let vm = {}; //创建vm实例对象
vm._data = data = obs //obs赋值给data,data赋值给vm._data
function Observer(obj) {
const keys = Object.keys(obj); //获取obj对象中的keys
keys.forEach((key)=>{ //遍历每个key
Object.defineProperty(this, key, { //this向外找到为Observer
get() {
return obj[key]; //获取对象中某个
},
set(value) {
obj[key] = value;
}
})
})
}
</script>
而vue在实现相应功能还加了一些新的
1.数据代理,就是不需要通过_data来改变属性,参考前面内容。
2.即使是多层对象,每个对象都有相应的setter和getter(因为用了递归)。

Vue.set()方法
当在写完代码后,想在data中加一些数据(如增加属性值),不能直接在里面添加值,因为没有对应的getter和setter,也就不能进行响应式了,这是因为数据从data到_data的过程会增加setter和getter,而直接添加进_data就没有了,而且还不能直接在data里加值,因为vm中的属性本身就是通过数据代理来的,更不能直接在vm实例中添加。这时候就需要用到Vue.set()方法了,因为该方法会给添加的属性增加相应的getter和setter。
<div id="testBox">
<h1>名字:{{name}}</h1>
<h1>年龄:{{age}}</h1>
<h1>幼儿园:{{people.kindergarten}}</h1>
<h1>哪来的:{{people.address}}</h1>
<h1>母亲名字:{{people.family.mother}}</h1>
<h2>朋友:</h2>
<ul>
<li v-for="(friend,index) in people.friends" :key="index">
{{friend.name}}--{{friend.age}}
</li>
</ul>
<button @click="clickFun">点击增加幼儿园属性</button>
</div>
<script type="text/javascript">
const vm = new Vue({
el:'#testBox',
data:{
name:'野原新之助',
age:'6岁',
people:{
address:'蜡笔小新',
family:{
father:'野原广志',
mother:'野原美伢'
},
friends:[
{name:'饭团头',age:'6岁'},
{name:'妮妮',age:'5岁'}
]
}
},
methods: {
clickFun() {
//Vue.set(target,key,val)
Vue.set(this.people, 'kindergarten', '向日葵班');
//或者this.$set(this.people, 'kindergarten', '向日葵班');
}
},
})
</script>
</body>
</html>
还没添加


添加后


数组

数组内容没有相应的setter和getter,因此直接改变数组内索引对应的内容,不会改变页面的内容,即不会响应式,但是数据确实已经改变了。而对象的话,从前面我们已经知道,对象的属性会有getter和setter,因此是响应式的。


数组的响应式方法
1.push
尾部插入元素
2.pop
尾部删除元素
3.shift
头部删除元素
4.unshift
头部添加元素
5.splice
可以增删改
删除/插入/替换元素
删除元素:第二个参数传入你要删除几个元素(如果没有传,就删除后面所有元素)
替换元素:第二个参数,表示我们要替换几个元素,后面是用于替换前面的元素
插入元素:第二个参数,传入0,并且后面跟上要插入的元素
通用的方法就是splice(索引,删除元素个数,添加的元素),如果删除元素个数不为0,就是替换;如果删除元素个数为0,则是插入。
6.sort
排序
7.reverse
反转元素
8.vue.set或者vm.$set(代码可以用this)(修改的对象,索引值,想要修改成为的值)
那么这些响应式的方法是怎么实现响应式的?
以push为例:数组原型的push与受到Vue管理的数组数据的push不是同个方法。Vue管理的push除了有原数组的添加功能外,还加了重新解析模板的功能,也就是跟之前data一改变,进行响应式同样的道理。


被折叠的 条评论
为什么被折叠?



