【问题标题】:Change detection with Observable vs Immutable使用 Observable 和 Immutable 进行变更检测
【发布时间】:2015-12-16 13:44:10
【问题描述】:

所以我阅读了this article 关于 Angular 2 更改检测的内容,但在阅读之后我变得更加困惑,所以我开始阅读一些导致更多困惑的 cmets。

不可变对象

如果一个组件只依赖于它的输入属性,并且它们是 不可变的,那么当且仅当它的一个组件可以改变 输入属性改变。因此,我们可以在变化检测树中跳过组件的子树,直到发生这样的事件。发生这种情况时,我们可以检查一次子树,然后禁用它直到下一次更改(灰色框表示禁用更改检测器)。

所以如果 {{todo.text}}todo.checked 更改我们标记我们的 todo:Todo 发生了变化

但是根据我的理解,我们可以创建级联的不可变对象。

如果我们积极地使用不可变对象,那么很大一部分 大多数情况下更改检测树将被禁用。

@Component({changeDetection:ChangeDetectionStrategy.OnPush})
class ImmutableTodoCmp {
  todo:Todo;
}

所以在这种情况下,{{todo.text}}todo.checked 上的任何更改都不会被注意到,对吧?只有当 Todo 被推送时,我们才会看到变化?

可观察对象

如果一个组件只依赖于它的输入属性,并且它们是可观察的,那么当且仅当它的一个输入属性发出一个事件时,这个组件才能改变。因此,我们可以在变化检测树中跳过组件的子树,直到发生这样的事件。发生这种情况时,我们可以检查一次子树,然后禁用它直到下一次更改。

虽然它可能听起来类似于不可变对象的情况,但它是完全不同的。如果您有一棵具有不可变绑定的组件树,则更改必须从根开始遍历所有组件。在处理 observables 时情况并非如此。

我不明白 Observables 与 Immutables 有何不同,在 Todo 应用的这种特定情况下,哪种方法更好?

【问题讨论】:

    标签: angular


    【解决方案1】:

    所以,从现在开始就像我们是 5 岁的孩子一样。

    这是JohnCmp。 John 是一个接受两个输入的组件,一个name: {first: 'John', last: 'Smith'} 和一个age: 20

    如果name 是可变的会发生什么?好吧,有人可以将它传递给John 并持有对它的引用。这样 John 和 ANY 数量的其他对象或服务可以持有对该 name 对象的引用。这意味着他们可以改变它,比如做name.last = 'foo'。约翰的名字改变了,但他没有收到新的名字。他仍然有对那个name 对象的引用,但它发生了变异。

    如果我们想检测这个,我们必须积极地检查namename.first、name.last,以此类推我们传递的每个对象的每个属性。做name === newName 并比较参考文献会容易多少,嘿? 如果 name 是不可变的,我们就不需要疯狂检查每个属性,我们可以检查引用并知道对象是否快速更改

    好的,现在,假设没有人持有对 Johnname 对象的引用。所以如果他们想给他一个新名字,他们必须传入一个 NEW 名字对象。然后John 在他的输入改变时改变。这就是这里的意思:

    如果一个组件只依赖于它的输入属性,并且它们是不可变的,那么当且仅当它的一个输入属性发生改变时,这个组件才能改变。因此,我们可以跳过组件在变化检测树中的子树,直到发生这样的事件。

    好的,这就是基本情况吧?现在我们不必担心检查每个属性,我们只需检查引用没有改变。大大改善!但是对象可能很大。所以people 数组是不可变的ArrayJohns,它们是不可变的,names 也是不可变的。所以为了改变约翰的名字。您需要生成一个 new 名称、一个 new John 和一个 new 人员数组。

    所以它们都变了,需要遍历整棵树。这就是O(n)。因此,这个小评论:

    如果您有一棵具有不可变绑定的组件树,则更改必须从根开始遍历所有组件。

    但是

    在处理 observables 时情况并非如此。

    为什么?

    Observables 发出事件。他们不需要像不可变对象那样更改所有内容,他们只需要emit 更改事件。因此,在他的示例中,您没有需要重新创建并因此重新评估树上的所有更改的不可变“数组”。现在你有一个people observable,当它改变时触发事件。 John 也会收到一个 observable。

    因此,您可以在John 中触发一个事件,告诉他他的名字已更改,而无需在people 中触发一个事件或类似的事情。避免您重新扫描所有内容以进行更改,从而将复杂性降低到O(log n),根据此引用:

    如您所见,这里的 Todos 组件只有一个对 todos 数组的 observable 的引用。 所以它看不到单个待办事项的变化

    (强调我的)。

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      我不明白 Observables 与 Immutables 有何不同,在 Todo 应用的这种特定情况下,哪种方法更好?

      想象一下,你有一个节点树,每个节点都有一点表示“我可能已经改变了”。使用Observable,我们正在谈论events getting emitted;事件被向上调度。换句话说:

      • Todo_ChangeDetector 将被标记,
      • 然后走上树,Todos_ChangeDetector 将被标记,
      • 然后走上树,App_ChangeDetector 将被标记,
      • 然后开始正常的变化检测

      假设您有 2 个待办事项列表:

      1. 购物清单。
      2. 当天的会议列表(工作?)。

      您当前显示的购物清单是Observable;例如下拉列表、导航药丸等。这两个列表下的所有待办事项都可以是Immutable;例如您不是会议组织者,无法更改会议。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-03
        • 1970-01-01
        • 2019-03-19
        相关资源
        最近更新 更多