Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Angular 2在ngFor中重建DOM,即使使用trackBy_Javascript_Angular_Ngfor - Fatal编程技术网

Javascript Angular 2在ngFor中重建DOM,即使使用trackBy

Javascript Angular 2在ngFor中重建DOM,即使使用trackBy,javascript,angular,ngfor,Javascript,Angular,Ngfor,我非常不需要为一个值数组重建DOM,每个值都包含一个表示YouTube livestream的对象。我正在使用ngFor对livestreams进行迭代 然而,当livestreams发生变化时(这可能是因为用户想要改变观看顺序,所以他们最想观看的livestream位于顶部-请参见下面的reorder()),ngFor会重建元素,这会导致YouTube嵌入从DOM中删除,然后重新插入;这会导致运行的livestreams停止播放,并重新加载它们,这需要一秒钟左右的时间。这不是最优的 我曾尝试

我非常不需要为一个值数组重建DOM,每个值都包含一个表示YouTube livestream的对象。我正在使用ngFor对livestreams进行迭代

然而,当livestreams发生变化时(这可能是因为用户想要改变观看顺序,所以他们最想观看的livestream位于顶部-请参见下面的
reorder()
),ngFor会重建元素,这会导致YouTube嵌入从DOM中删除,然后重新插入;这会导致运行的livestreams停止播放,并重新加载它们,这需要一秒钟左右的时间。这不是最优的

我曾尝试使用
trackBy
以livestream(我对象中的一个属性)的名称而不是对象本身来跟踪这些值,但这似乎并没有解决问题

模板: *ngFor模板中使用的trackBy功能不起作用 重新排序功能
由于上面的实现不必要地重建了DOM,我正在寻找解决这个问题的方法。到目前为止,我的想法是创建一个自定义的类似于*ngFor的结构化指令,使用flexbox来管理订单,或者只是在我现有的实现中确定一个小的更改来解决这个问题。

这是因为
public visibleLivestreams():Livestream[]{
每次调用时都返回一个新数组。
trackBy
在这里无能为力

而是将结果指定给属性,并绑定到此属性

constructor() { // or some other event that causes the result to change
    this.liveStreams = this.userPrefs.visibleLivestreams();


这是一种更有效的方法,因为使用代码更改检测调用
userPrefs.visibleLivestreams()
每次运行更改检测时,这可能非常频繁。

当页面第一次加载时,ngFor加载整个列表。之后,如果您当时正在循环的列表中有更改,则只会反映更新的项目。

好的,但当livestreams确实发生更改时,我需要在不同的顺序,我仍然需要重新分配
这个.liveStreams
,这将导致元素被删除和重新添加,对吗?你当然可以这样做。只需重复使用以前的数组,并根据需要删除和添加元素,而不是创建新数组。我现在正在
对数组进行排序(一个可以改变原始数组的可变函数)在更改时,*ngFor仍在删除和添加元素。想法?你可以在一个Plunker中复制。当然!单击“旋转”可以看到livestreams重新加载(奇怪的是底部的除外)。在保持重新排序能力的同时,我需要防止这种重新加载效果。
public visibleLivestreams() : Livestream[] {

   let livestreams = [
       { name: 'a', url: 'youtubeUrl', ... }, 
       { name: 'b', url: 'youtubeUrl', ... },
       { name: 'c', url: 'youtubeUrl', ... }
   ];

   // _visibleLivestreams, used below to order and filter, 
   // is a simple, ordered, array of strings representing 
   // the livestream names, stored in localstorage.

   return livestreams
        .filter(l => this._visibleLivestreams.indexOf(l.name) != -1);
        .sort((a, b) => this._visibleLivestreams.indexOf(a.name) < this._visibleLivestreams.indexOf(b.name) ? -1 : 1);
}
public livestreamTrackByFn(index: number, item: Livestream) : string {
    return item.name;
}
/**
 * Reorders elements of the livestreams array by shifting off the
 * 0th element, and pushing it the last position in the array.
 * 
 * Calling this function results in the DOM being rebuilt!
 */
public rotate() : void {
    // shift element off _visibleLivestreams
    let elem = this.userPrefs.visibleLivestreams.shift();
    // push element onto _visibleStreams
    this.userPrefs.visibleLivestreams.push(elem);
}
constructor() { // or some other event that causes the result to change
    this.liveStreams = this.userPrefs.visibleLivestreams();
<livestream-player *ngFor="let livestream of userPrefs.visibleLivestreams"        [video]="livestream.url | sanitize:'resource'">