Vue.js:检测嵌套数据

时间:2016-10-20 00:11:39

标签: vue.js vue-component

以下是我的代码的简化版本:

Vue.component('entry', {
  template: '\
    <div>\
        <label>Name: <input type="text" v-model="entry.name"></label>\
    </div>\
  ',
  props: ['entry']
});

Vue.component('entries', {
  template: '\
    <div>\
      <entry v-for="entry in entries" :entry="entry"></entry>\
      <pre>{{ combined }}</pre>\
    </div>\
  ',
  props: ['entries'],
  computed: {
    combined: function() {
      combined = [];
      this.entries.forEach(function(entry) {
        combined.push(entry.name);
      });
      return combined.join("\n");
    }
  }
});

var entries = [
  {name: "Entry 1"},
  {name: "Entry 2"},
  {name: "Entry 3"}
];

JSFiddle:https://jsfiddle.net/msw3Lx98/3/

顶级组件(entries)获取对象列表,并为每个组件创建一个子组件(entry)。子组件将条目数据绑定到输入。

当用户通过键入其中一个输入来修改数据时,顶级组件需要将更新后的combined值推送到单独的代码位。

我对观察者模型的理解是,如果顶级组件监视entries,它可以检测到列表中添加或删除内容的时间,但是当 中的数据时进入变化。

但是,顶级组件显然确实以某种方式看到此类更改,因为当用户键入输入时,combined的值会更新。

有没有“正确”的方法来检测这种变化?

以下是我探索过的几个选项:

  • 在子组件上定义updated方法。在该方法中,发出自定义事件,并在父级中处理此事件。这是相当尴尬的,我认为它不会很好地扩展。
  • 在父级上定义beforeUpdate方法 - 只要子组件发生更改,就会运行此(但不是updated)。我不确定为什么,它对我来说闻不对。
  • 在顶级组件中,观看combined属性。我对这项工作感到惊讶,但确实如此。这似乎是最直接的选择,但是从Vue文档来看,计算属性是可以观察的并不明显,所以我不愿意依赖它。

1 个答案:

答案 0 :(得分:1)

VueJS的承诺之一是它允许开发人员在考虑业务逻辑时正常编码,而框架使用 Reactivity system 来处理性能。

VueJS通过在实例化组件时定义已知对象和数组上的getter和setter来实现此目的。

这是一个更新的小提琴(从您的版本分叉):https://jsfiddle.net/6wkyfxs6/3/

正如您所看到的,我已经为addNewEntry添加了一个方法,允许您添加&#34;元素4&#34;列表。

前3个元素具有观察者方法并不奇怪,因为它是在Vue实例化时构造的。但是如果你添加&#34;元素4&#34;在我最初没有出现的新小提琴中,即使它被观察到并且通知了变化。这就是反应系统​​的工作原理。

在更深入的检查中,如果您在条目组件中设置window.entries = this.entries并检入控制台,您会注意到它顶部有一个观察者方法(entries.__ob__)水平。这是一个截图(取自谷歌Chrome中的本地版本,而不是jsFiddle):

Vue.js observer for an array object

与使用脏检查的Angular 1.x不同,这是Vue用来更新和通知自身整体数组中的更改的内容。因此,只要您在Vue中更改某些内容, Reactivity System 就会触发并设置所有新对象和修改对象的观察者(以及getter / setter)。

如果直接在javascript中添加或更改对象,则不会触发反应系统。特别是在数组的情况下(如您的示例所示),此处显示了一些注意事项:https://vuejs.org/guide/list.html#Caveats,但您的示例避开了这些警告。

总之,VueJS允许像我们这样的开发人员在编写业务逻辑时正常编写代码,同时负责性能优化。除非您遇到一些问题,否则我认为您不应该使用任何updatedbeforeUpdate方法 - 在这种情况下,首选应该是提交错误报告而不是工作-arounds。