【问题标题】:What is the purpose of ngForTrackBy in the NgForOf directiveNgForOf 指令中 ngForTrackBy 的目的是什么
【发布时间】:2020-11-12 08:01:37
【问题描述】:

来自Angular的source code,下面的sn-p让我很困惑。

 /**
   * A function that defines how to track changes for items in the iterable.
   *
   * When items are added, moved, or removed in the iterable,
   * the directive must re-render the appropriate DOM nodes.
   * To minimize churn in the DOM, only nodes that have changed
   * are re-rendered.
   *
   * By default, the change detector assumes that
   * the object instance identifies the node in the iterable.
   * When this function is supplied, the directive uses
   * the result of calling this function to identify the item node,
   * rather than the identity of the object itself.
   *
   * The function receives two inputs,
   * the iteration index and the node object ID.
   */
  @Input()
  set ngForTrackBy(fn: TrackByFunction<T>) {
    ...
      }
    }
    this._trackByFn = fn;
  }

还有here 来自官方文档的一个示例,其中传递了trackBy 函数。

trackById(index: number, hero: Hero): number { return hero.id; }

源码说明

当提供此函数时,指令使用调用此函数的结果来标识项目节点,而不是对象本身的标识。

但是在上面的例子中,我们无论如何都传递了对象本身的身份(return hero.id;),但是通过一个附加函数。为什么我们需要那个?如果我们不传递任何这样的函数,Angular 不会按照文档默认执行它所做的事情,即获取对象本身的身份吗?

跟踪器函数的显式传递与 Angular 通常没有它时所做的有什么不同?

谢谢。

【问题讨论】:

    标签: angular angular-directive ngfor


    【解决方案1】:

    我绝对可以看出它的措辞是多么令人困惑。但是当它说“而不是对象本身的身份”时,

    【讨论】:

      【解决方案2】:

      Angular 会检查内存中的非原始类型的引用。如果不传入trackById 方法,每次数组更改时,它都会认为每个对象都是新对象并重新创建所有DOM 节点。

      如果传递trackById,它将检查原始对象与新对象,如果它们的id属性相同,则表示它们是相同的对象,不会重新绘制该DOM节点.

      这是一个您也可以运行的示例,它只是普通的 javascript

      let obj1 = {id: 1, name: 'test'};
      let obj1a = {id: 1, name: 'test'};
      let prim1 = 1;
      let prim2 = 1;
      
      const checkById = (a, b) => {
        return a.id === b.id;
      }
      
      // obj1 and 1a are not the same, because they are different references in memory
      console.log("obj1 === obj1a", obj1 === obj1a);
      
      // ob1 and obj1a are the "same" to us though, because the ID property is the same
      console.log("checkById(obj1, obj1a)", checkById(obj1, obj1a));
      
      // primitives would be equal
      console.log("prim1 === prim2", prim1 === prim2);

      【讨论】:

      • 所以如果我做对了,这类似于 &lt;li v-for="item in items" :key="item.message"&gt; {{ item.message }} &lt;/li&gt; 的 Vue 语法除了在 Angular 的情况下,我必须定义一个跟踪函数来返回 DOM 节点应该使用的索引被跟踪。
      • 我不熟悉 Vue,但我猜它有一个内置的方法可以通过提供一个键来做同样的事情,这样它就可以比较这两个值。 Angular让你提供了一个自定义函数来运行,虽然我只用它来通过那个对象“键”来比较它,但也许还有其他属性或多个属性或其他一些你想要检查的逻辑,所以这允许更大的灵活性。
      猜你喜欢
      • 2011-11-12
      • 1970-01-01
      • 2011-02-17
      • 2012-10-05
      • 1970-01-01
      • 2021-08-29
      • 2022-11-30
      相关资源
      最近更新 更多