2016-12-04 4 views
3

У меня нет необходимости перестраивать DOM для массива значений, каждый из которых содержит объект, представляющий живой поток YouTube. Я использую ngFor, чтобы вырезать живые потоки.Угловая 2 восстанавливает DOM в ngДля того, когда используется trackBy

Однако при изменении прямых трансляций (это может быть потому, что пользователь хочет изменить порядок просмотра, поэтому прямые они хотят смотреть больше всего на вершине - см reorder() ниже), ngFor перестраивает элементы, который вызывает YouTube вставляется для удаления из DOM и повторно вставляется; что приводит к запуску livestreams, чтобы остановить игру, а также перезагружает их - что занимает секунду или около того. Это не оптимально.

Here is a Plunkr of my issue

Я пытался использовать trackBy следовать значения по имени прямой трансляции (свойство в моем объекте), а не сам объект, но это, кажется, не решен вопрос ,

Шаблон:

<livestream-player *ngFor="let livestream of userPrefs.visibleLivestreams(); trackBy: livestreamTrackByFn"  [video]="livestream.url | sanitize:'resource'"> 
</livestream-player> 

Массив элементов: userPrefs.visibleLivestreams()

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); 
} 

Не-рабочая функциональность trackBy используется в * ngFor шаблон

public livestreamTrackByFn(index: number, item: Livestream) : string { 
    return item.name; 
} 

функциональность Reorder

/** 
* 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); 
} 

Как указано выше, перестройка DOM излишне, я действительно ищу обходной путь для этой проблемы. Мои мысли до сих пор создают настраиваемую структурную директиву *ngFor, используя flexbox для управления заказом или просто определяя небольшое изменение в моей существующей реализации, которая устраняет эту проблему.

+0

http://stackoverflow.com/questions/7434230/how-to-prevent-an-iframe-from-reloading-when-moving-it-in-the-dom http://stackoverflow.com/questions/ 16333749/sort-list-without-reloading-iframe – yurzui

ответ

0

Это потому, что public visibleLivestreams() : Livestream[] { возвращает новый массив каждый раз, когда он называется. trackBy здесь не может.

Скорее присвоить результат свойству и привязать его к этому свойству.

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'"> 

Это способ более эффективна, потому что с обнаружением изменений коды вызывает userPrefs.visibleLivestreams(); запускается каждое обнаружение изменения времени, и это может быть довольно часто.

+0

Хорошо, но когда livestreams * do * меняются, и мне нужно их повторно отобразить в другом порядке, мне все равно придется переназначить 'this.liveStreams', что приведет к тому, что элементы будут быть удалены и повторно добавлены в любом случае, не так ли? – ReactingToAngularVues

+0

Вы можете это сделать, конечно. Просто повторно используйте предыдущий массив и удалите и добавьте элементы в зависимости от ваших потребностей, а не создайте новый массив. –

+0

Я теперь '.sort'ing массив (изменяемая функция, которая изменяет исходный массив на месте) при изменении и * ngFor все еще удаляет и добавляет элементы. Идеи? – ReactingToAngularVues

 Смежные вопросы

  • Нет связанных вопросов^_^