关于响应式:
所谓“响应式”,就是是指data改变后,Vue给予使用该data的代码一个响应。例如视图渲染中使用了data,该data被改变后,该视图会自动更新。
这涉及到一个代理的问题,例如JS中的
Object.defineProperty:
它可以给对象添加一个属性value,以及添加getter/setter,这个getter/setter用于对这个属性value的读写进行监控。
在Vue中,Vue就是作为一个代理,监控其中数据的内容是否有变化。
例如:
const vm = new Vue({
el: '#app',
data: {
name: 'Xie'
}
})
我只需要写vm.name='Rua'
,就相当于直接修改了data的name,页面会直接显示新的name:Rua。
这就相当于让vm成为data的代理(proxy),并对data中所有属性进行监控,以防data属性变化时vm不知道。
毕竟,vm必须要知道data属性的变化才能调用render(data)
,这样页面才会刷新,所谓的数据响应式才能实现。
即UI=render(data)
简单的理解一下,就是房东和中介的关系,中介帮房东全权处理各种问题,作为房东房客相互传达信息的一方,这样房东当然很省心。同时中介也不希望房客能直接找到房东,有时会引起不必要的麻烦。
而对于对象中新增的key,Vue没法事先监听和代理,这种场合下需要使用set来新增key(Vue.set
或this.$set
)来创建监听和代理从而实现数据的响应式即ui的更新。不过最好还是提前把属性都写好,没必要的时候不要新增key。(但是数组无法做到不新增key)
关于api
Vue篡改了JS中的7个api,他们分别是:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
提到这个就不得不提到原型,在访问一个对象的属性时,不仅寻找该对象本身的属性,还会搜寻这个对象的原型以及原型的原型直到找到该属性(或者到原型链末尾都找不到),通过在array外包裹一层array已有的api,使得对象在通过原型链向前寻找这七个属性时在找到Vue篡改的api后就停止。
例如我在Vue中使用array.push()
,这个数组实际不会不会访问到真正的array.push()
,而是访问到"vueArray.push()
(即Vue篡改过的push()
)",这个push()
在array.push()
的外一层,就是说实际上这个vueArray.__proto__
就是指向了Array
的。(佛辣说的什么乱七八糟的)
通过这7个api对数组进行增删的操作,就会自动处理监听和代理并更新UI了。
这是我对Vue数据响应式的一些理解,仍在初级学习阶段,如后期发现错误还会回来改的233