Vue - 添加的嵌套属性变得有反应,但为什么呢?

Vue - Added Nested Attributes Become Reactive But Why?

根据文档 (https://vuejs.org/v2/guide/reactivity.html),我的印象是对象的所有属性都需要在 Vue 数据对象中才能反应,除非使用 [=11= 显式添加它们], 或 this.$set(object, key, value).

但是,我将 Rails 与 Vue 一起使用,我在表单中收集的任何数据属性,无论它最初是否在数据对象中,都会变成反应性的。我正在使用 Jbuiler 构建 JSON 对象,但我认为这不会影响反应性,因为如果我删除那里的属性,它们在以表单收集时仍然是反应性的。我已经尝试过 Rails 中对象上的属性和不在 Jbuilder 中或不通过控制台添加的属性。都变得被动了。这很好,但不是我期望的行为,所以我想了解它。

这是一个例子...

# Product attributes: name, code (note: not 'location'!) 

# Rails Controller

def new
  @product = Product.new
end


# JS
var product = gon.product // using Gon gem to pass variables

var app = new Vue({
  el: element,
  data: function() {
      return {
      id: id,
      product: product
    } 
  }
)}


# HTML
<div class="col-sm-3">
  <input type="text" v-model="product.code" class="form-control form-control-sm" />
</div>
<div class="col-sm-3">
  <input type="text" v-model="product.location" class="form-control form-control-sm" />
</div>
<div>
  Product Code: {{ product.code }}
  Product Location: {{ product.location }}
</div>

当我开始在 product.location 字段中输入时,输出立即出现在屏幕上,因此它看起来是反应式的。检查控制台中的对象显示 reactive getterproduct.locationreactive setter。该属性最初不在 Vue 控制台开发工具中,但在我开始在该字段中输入时它会立即出现。

那么,是什么原因呢?

来自上面的文档 link:

When you pass a plain JavaScript object to a Vue instance as its data option, Vue will walk through all of its properties and convert them to getter/setters using Object.defineProperty.

换句话说,组件实例上定义的所有内容都是反应性的。这允许 watcher 实例更新所有依赖值和虚拟 DOM.

$set 方法用于确保反应性适用于深度嵌套的 objects/arrays 或以前未定义的属性。

此外,v-model 指令使用 $set 方法来更新值,因此即使值最初没有 getter 和 setter,这些也会在值更新后添加.