一.一张图追踪数据响应式变化
数据响应式是Vue 最独特的特性之一,是其非侵入性的响应式系统。数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新。
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。尽管如此我们还是有一些办法来回避这些限制并保证它们的响应性
二.vue数据响应式的含义是什么?
vue能实现对实例中声明过的数据进行监听。当数据发生变化时,试图会根据变化内容进行重新渲染页面,从而简化程序员的工作。
三.如何做到数据响应式?
通过 object.defineProperty(),配合 getter 和 setter 实现监听,同时引入代理,负责对象的属性读写,代码如下:
复制代码
// 需求五:就算用户擅自修改 myData,也要拦截他
let myData5 = {n:0}
let data5 = proxy2({ data:myData5 }) // 括号里是匿名对象,无法访问
function proxy2({data}{
let value = data.n
Object.defineProperty(data, 'n', {
get(){
return value
},
set(newValue){
if(newValue<0)return
value = newValue
}
})
// 就加了上面几句,这几句话会监听 data
// data5 就是 obj
console.log(`需求五:${data5.n}`)
myData5.n = -1
console.log(`需求五:${data5.n},设置为 -1 失败了`)
myData5.n = 1
console.log(`需求五:${data5.n},设置为 1 成功了`)
复制代码
vm = new Vue({data:myData}),会让vm成为myData的代理,对myData的所有睡醒进行建空,防止myData发生变化。只有代理vm知道了变化,才能根据变化重新渲染视图。
四.如何给数据新增key
1.普通的对象
使用Vue.set 或者this.是为了防止命名冲突)
methods: {
setB() {
Vue.set(this.obj, 'b', 1)
// 等价于 this.$set(this.obj, 'b', 1)
}
}
复制代码
结果:
新增key,自动创建代理和监听,触发UI更新
2.数组对象
代码:
class VueArray extends Array{
push(...args){
const oldLength = this.length
super.push(...args)
console.log('你push了')
for(let i = oldLength; i<this.length; i++){
Vue.set(this, i ,this[i])
}
}
}
//这不是Vue的真实实现,只是展示下思路
复制代码
原理就是新增一层原型,供vue使用。
具体就这么多,后面了解深入之后再进行更新。