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