Vue 数据响应式

51 阅读2分钟

一、Vue 对 data 做了什么

Object.defineProperty

  • 可以给对象添加属性 value
  • 可以给对象添加 getter / setter
  • getter / setter 用于对属性的读写进行监控

代理(设计模式)

  • 对 myData 对象的属性读写,全权由另一个对象 vm 负责
  • 那么 vm 就是 myData 的代理(类比房东租房)
  • 比如 myData.n 不用,偏要用 vm.n 来操作 myData.n

vm = new Vue({data: myData})

  1. 会让 vm 成为 myData 的代理(proxy)
  2. 会对 myData 的所有属性进行监控
  3. 为什么要监控,为了防止 myData 的属性变了, vm 不知道,vm 知道了又如何?知道属性变了就可以调用 render(data) !
  4. UI = render(data)

image.png

二、数据响应式

什么是响应式

  • 若一个物体能对外界的刺激做出反应,它就是响应式的
  • 非侵入性的响应式系统是Vue 最独特的特性之一。数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新。

Vue 的 data 是响应式

  • const vm = new Vue({data: {n: 0}})
  • 如果修改 vm.n,那么 UI 中的 n 就会响应
  • Vue 2 通过 Object.defineProperty 来实现数据响应式

响应式网页

  • 如果改变窗口大小,网页内容会做出响应,那就是响应式网页
  • 但是要注意,用户没事不会拖动网页大小的

Vue.set 和 this.$set

  1. 作用
  • 新增 key
  • 自动创建代理和监听(如果没有创建过)
  • 触发 UI 更新(但并不会立刻更新)
  1. 举例
  • this.$set(this.object, 'm', 100)

篡改数组的 API

Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

   push()
   pop()
   shift()
   unshift()
   splice()
   sort()
   reverse()

你可以打开控制台,然后对前面例子的 `items` 数组尝试调用变更方法
比如 example1.items.push({ message: 'Baz' })
  • 这 7 个 API 都会被 Vue 篡改,调用后会更新 UI
  • 怎么篡改的
class VueArray extends Array{
  push(...args){
    const oldLength = this.length // this 就是当前数组
    super.push(...args)
    console.log('你 push 了')
    for(let i = oldLength; i<this.length; i++){
      Vue.set(this, i, this[i])
      // 将每个新增的 key 都告诉 Vue
    }
  }
}
注:这不代表 Vue 的真实实现,仅是举例