Vue 对 data 做了什么
当我们把一个JavaScript对象传入Vue实例作为data选项时
Vue将遍历此对象所有属性,使用Object.defineProperty转为 getter/setter
getter 和setter
get 姓名(){
return this.姓 + this.名
}
get 姓名()是一个计算属性而不是函数,只不过是以函数形式定义的
这种写法叫getter,用于获取一个值; getter用法:在函数前加get,调用时不加()
set 姓名(xxx){
this.姓 = xxx[0]
this.名 = xxx.substing(1)
}
obj3.姓名 = '郭碧婷'
setter接收一个新的值,触发set函数; 通过计算属性,设置原始属性
姓名:(...) 可以对姓名读和写,但是并不存在姓名这个属性
姓名是通过get,set来模拟对n的读写操作,getter和setter用于对属性的读写和监控
Object.defineProperty()
可以给对象添加属性 value
可以给对象添加getter和setter
var _xxx = 0
Object.defineProperty(obj, 'xxx',{
get(){return _xxx},
set(value){_xxx = value}
})
定义完一个对象之后,想在它身上额外的增加新的get、set
通过Object.defineProperty(),定义的get、set是虚拟的
let data2 = {}
data2._n = 0
Object.defineProperty(data2,'n',{
get(){
return this._n
},
set(value){
if(value < 0) return
this._n =value
}
})
代理
let data3 = proxy({data:{n:0}})
function proxy(options)
const {data} = options
function proxy({data})
const obj ={}
Object.defineProperty(obj, 'n',{
get(){return data.n}
set(value){
if(value<0) return
data.n = value
}
})
当设置obj的n,就设置data的n;不管你对obj做什么,他都把事情对data做一遍,obj就是代理
let maData5 = {n:0}
let data5 = proxy2({data:maData5})
function proxy2({data}){
let value = data.n
Object.defineProperty(data, 'n', {
get(){return value}
set(newValue){
if(newValue < 0) return
value = newValue
}
})
}
总结
Object.defineProperty
可以给对象添加属性value
可以给对象添加getter,setter
getter,setter用于对属性的读写进行监控
代理(设计模式)
对myData 对象属性的读写,全权由另一个对象vm负责
vm就是myData的代理
比如不用myData.n不使用,反而使用vm.n来操作myData.n
vm = new Vue({data: myData})
会让vm 成为 myData的代理(proxy)
会对myData的所有属性进行监控
防止myData的属性变了,vm不知道
vm知道之后,就可以调用render(data)
UI=render(data)
全程都在修改data:{n:0},没有生成新的{n:0},都是在{n:0}这个对象上修改的
然后得到一个被修改的对象,在此基础上产生一个代理,最后只剩代理对象和被修改的原始对象
数据响应式
options.data
会被vue监听,data会被篡改,本来的n变成get(n)set(n)
会被vue实例代理,const vm = new Vue({}) vm就是代理
每次对data的读写都会被vue监控,不管是data本身,还是它的代理都会被监控
vue会在data变化时更新UI
Vue.set和this.$set
作用:新增key
自动创建代理和监听 如果没有创建过
触发UI更新 但不会立即更新
this.$set(this.obj, 'm',100)
因为Object.defineProperty(obj, 'n', {...})
必须有一个'n'才能监听代理obj.n,如果没写,vue会给出一个警告
vue只会检查第一层属性;写了n,修改n2不会显示n2的内容,vue无法监听一开始不存在的n2
data中的数组怎么声明所有key
class VueArray extends Array{
push(...args){
const oldLength = this.length
super.push(...args)
for(let i = oldLength; i<this.length; i++){
Vue.set(this, i, this[i])
}
}
}
如果调用第一层push,我就去调用我下一层的push,调用父类上的push,多加一层属性
7个变异方法
push() 新增
pop() 弹出
shift() 弹出第几个
unshift() 在第一个处新增
splice() 从中间删除某一项
sort() 对所有数据重新排序
reverse() 倒序
详细资料点击:响应式原理