Vue 最独特的特性之一,使其响应式系统。数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新。
什么是响应式?
我给你一拳,你会喊疼,那你就是响应式的。
若一个物体能对外界的刺激做出响应,那么它就是响应式的。
思考一个问题,Vue 到底对 data 做了什么呢?
看一个示例代码
index.html
<body>
<div id="app"></div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
</body>
main.js
const Vue = window.Vue
const myData = {
n:0
}
new Vue({
data: myData,
template: `
<div>{{n}}</div>
`
}).$mount('#app')
setTimeout(() => {
myData.n += 10
}, 0)
console.log(myData)
控制台
{__ob__: we}
n: (...)
__ob__: we {value: {...}, dep: ce, vmCount: 1}
get n: f ()
set n: f (t)
__proto__: Object
可以看到,在将 data 传给 Vue后,Vue 会将它篡改。
Vue 为对象添加了 getter/setter 。
getter/setter 用于对属性的读写进行监控。
那么 Vue 是如何为对象添加属性的呢?
使用object.difineProperty()
方法。
Object.defineProperty( ) 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
语法
Object.defineProperty(obj, prop, descriptor)
- obj -- 要在其上定义属性的对象。
- prop -- 要定义或修改的属性的名称。
- descriptor--将被定义或修改的属性描述符。
返回值
被传递给函数的对象。
vm=new Vue({data:myData})
- 会让 vm 成为 myData 的代理(proxy)
- 会对 myData 的所有属性进行监控,当 myData 改变时,vm可以马上知道,并render(data),更新视图界面

Vue数据响应式总结
响应式即对外界的变化做出的反应的一种形式。
const vm = new Vue({data:{n: 0}})
当修改 vm.n 或 data.n 时,render(data...) 中的 n 就会做出响应的响应。
这个联动的过程就是 vue 的 数据响应式。
vue 目前通过 Object.defineProperty 来实现数据响应式。
Vue 的data有bug?
看一段代码:
import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;
new Vue({
data: {
obj: {
a: 0 // obj.a 会被 Vue 监听 & 代理
}
},
template: `
<div>
{{obj.b}}
<button @click="setB">set b</button>
</div>
`,
methods: {
setB() {
this.obj.b = 1; //请问,页面中会显示 1 吗?
}
}
}).$mount("#app");
页面中并不会显示1
Vue 虽然对 data 中的属性(或对象中的属性)进行监听和代理,但是它却没有办法进行事先的监听和代理。
如果你在初始化 data 之后再添加属性,该如何实现?
一般对象
Vue.set(object, key, value)
或
this.$set(object, key, value)
作用
在 data 中添加新的属性。
自动创建为它创建代理和监听(如果没有创建过)。
数组
Vue 提供了七个数组变更方法。
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()