数据代理
1. Object.defineproperty(对象名,属性名,配置项):vue实现的底层原理技术
即控制新增的属性,是否可以被增删改等等。getter和setter为重要函数
可将外部改变应用到内部
Object.defineProperty(person,'age',{
// value:18,
// enumerable:true, //控制属性是否可以枚举,默认值是false
// writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true //控制属性是否可以被删除,默认值是false
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get(){
console.log('有人读取age属性了')
return number
},
//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
console.log('有人修改了age属性,且值是',value)
number = value
}
2. 数据代理的定义:通过一个对象代理对另一个对象中属性的操作(读/写)
options.data=vm._data=data
3. 基本原理
- 把data对象中所有属性添加到vm上
- 为每一个添加到vm上的属性,都指定getter和setter
- 在getter/setter内部去操作data中对应的属性
- setter为响应式setter,调用时会内部再调用方法,可以引起模板的重新解析,生成虚拟DOM,引起后续动作
数据劫持(监测数据原理)
当更新数据时:1. 加工data、2. vm._data=data
- vue会监视data中所有层次的数据
- 监测对象原理:
在加工data中,通过setter实现监视,且要在new Vue时就传入监测数据
const obs=new Observer(data) //Observer实例对象
vm._data=data=obs //数据赋值
function Observer(obj){
const keys=Object.keys(obj) //汇总所有属性,返回数组形式
keys.forEach((k)=>{ //为每一个属性添加数据代理
object.definProperty(this,k,{
get(){ return obj\[k\] }
set(val){ console.log( \`${k}被修改了\` ) }
})
})
}
- Vue.set(),用于后续添加的新属性,做响应式处理
Vue.set( target, key, val )
//或vm.$set( vm.student,'sex','女' )
- 局限:只能给data里某一个对象追加属性,而不能直接在data上追加
- 即不允许为vm或vm.data追加属性
- 监测数组原理:
-
不使用getter/setter,而是使用数组的方法
- 注意:不可以只操作数组索引值进行修改
-
通过包裹数组上的常用方法来实现
- vue操作:1.调用Array.prototype的数组方法、2.重新解析模板、更新页面
- 即这里的数组方法,不再是Array.prototype的数组方法
- pop、push、shift、unshift、splice、sort、reverse
- 即变更方法:能够引起数组变化的
- 若使用非变更方法,则修改后重新赋值原数组即可
hobby:['烫头','打游戏','玩'] //方法1:splice修改值 vm.student.hobby.splice( 0,1,'打台球' ) //['打台球','打游戏','玩'] //方法2:set设置属性修改值 Vue.set( vm.student.hobby,1,' 学习 ' ) //['烫头','学习','玩'] friends:[{name:'jack',age:35},{name:'tony',age:36}] //1、修改其中的值 this.student.frinends[0].name='张三' //即不要直接修改索引 //2、添加新的数据 this.student.frinendsun.unshift({ name:'jack',age:70 })
总结:
- 数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
- 数据劫持:加工data,为每个属性添加getter和setter
- 若该属性没有getter/setter,则vue无法监测并实时更新页面。若有则可以进行修改