Vue 实例的 data 属性

基本认识

  1. 作用:Vue 会递归将 data 的属性转换为 getter/setter 方法,从而使得 data 中属性能够响应数据变化。
  2. 类型: Object | Function
// Object 类型 data 属性
const vm = new Vue({
  data: { 
    name: 'IT白'
  }
}) 

// Function 类型 data 属性
const component = Vue.extend({
  template: '

My name is {{ name }}

', data: function () { return { name: 'IT白', } } })

创建 Object 类型与 Function 类型的data属性的异同

  • 相同点:Vue 都会为其生成相应的 getter/setter 方法。
  • 不同点:当组件被同一时间多次实例化时
      Object 类型:组件的所有实例都会引用同一个数据对象。当一个实例修改的自身的 data 属性,由于引用统一个数据对象,导致修改也将会在其它实例中呈现。
      Function 类型:每次创建组件实例时, Vue 都将通过调用该函数,创建一个全新副本的数据对象。当一个实例修改自身的 data 属性,由于每个实例中的 data 属性对象都是单独的副本,所以不会影响其它实例。

:如果将组件的 data 属性定义为 Object 类型,Vue 会抛出警告。


data 属性响应式原理

追踪数据变化
  • 准备:Vue 会遍历 data 对象(如果是 Function 类型,Vue 会先调用函数,创建对应对象),并将所有属性通过 Object.defineProperty() 转换成 getter/setter
  • collect as dependency:每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据属性记录为依赖。
  • notify:当 setter 被触发时,会通知 watcher。
  • trigger re-render:watcher 重新渲染关联的组件。
  • touch:如果实例修改 data 属性的值,将会触发 setter。
Vue 实例的 data 属性_第1张图片
Vue 官方文档插图
检测变化的注意事项

由于 JavaScript 的限制,Vue 无法检测对象属性的添加或删除,所以直接动态添加属性到 data 对象中,该属性为非响应式。

var vm = new Vue({
  data:{
    a:1
  }
})
// `vm.a` 是响应式的

vm.b = 2
// `vm.b` 是非响应式的

但是可以通过 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性,以及 Object.assign() 方法创建一个新的对象。

Vue.set(vm.someObject, 'b', 2)

// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
异步更新队列
  • Vue 在更新 DOM 时是异步执行的。
      只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。
      如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
      Vue 在内部对异步队列尝试使用原生的 Promise.thenMutationObserversetImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

  • 使用 .nextTick()
      为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。

你可能感兴趣的:(Vue 实例的 data 属性)