2017-09-01 29 views
0

當使用一個不可變模型對象的數組時,我一直無法使CSS轉換工作。Angular:內部不可變模型的動畫ngFor

角度是否需要對屬性進行就地更新才能使用,或者我做錯了什麼?

爲例:(https://plnkr.co/edit/PBSPtk9vMig7cxnHoJqA

export class Box { 
    constructor(public selected:boolean){ 
    } 
} 

function toggle(box:Box):Box{ 
    return new Box(!box.selected) 
} 

@Component({ 
    selector: 'my-app', 
    template: ` 
    <ul> 
    <li *ngFor="let box of boxes"> 
    <div 
    style="display:inline-block; width: 20px; height:20px; transition: 1s; margin:5px; cursor:pointer;" 
    [ngStyle]="{'background': box.selected?'green':'red'}" 
    > </div> 
    <button (click)="toggle_in_place(box)">toggle (in-place)</button> 
    <button (click)="toggle_replace_box(box)">toggle (replace box)</button> 
    <button (click)="toggle_replace_array(box)">toggle (replace array)</button> 
    </li> 
    </ul> 
    `, 
}) 
export class App { 

    boxes: Box[]; 

    constructor() { 
    this.boxes = [new Box(true), new Box(false), new Box(true)]; 
    } 

    toggle_in_place(box:Box){ 
    box.selected=!box.selected; 
    } 

    toggle_replace_box(box:Box){ 
    const index = this.boxes.indexOf(box); 
    this.boxes[index]=toggle(box); 
    } 

    toggle_replace_array(box:Box){ 
    this.boxes = this.boxes.map(v=>v===box?toggle(v):v); 
    } 
} 

在這裏,我想通過動畫的div顏色

[ngStyle]="{'background': box.selected?'green':'red'}" 

box.selected可以通過更新:

  • 更改就地房產(toggle_in_place),
  • 替換'box'模型(toggle_replace_box)
  • 替換整個數組(toggle_replace_array)。

但是toggle_in_place是唯一導致可見轉換的結果。

這是我必須生活的東西嗎?

回答

0

發生了什麼這裏:當數組更改ngFor比較新數組中的對象引用與舊的並重新呈現已更改的任何元素,這打破了css轉換。

爲了解決這個問題,ngFor可以被賦予一個跟蹤函數,然後用它代替參考比較。

要修復,指定跟蹤功能使用一個ID而不是對象引用:

trackingFunction(index:number, box:Box){ 
    return box.id; 
} 

有無ngFor使用它:

<li *ngFor="let box of boxes;trackBy:trackingFunction"> 

實施例: https://plnkr.co/edit/4OXemdSf1Hsm1NU6ZhzT

0

我認爲這是你必須忍受的。在後兩種情況下,由於您每次都要創建一個新的盒子實例,因此它沒有任何可以轉換的地方。

你或許可以創建一個基本上是一個包裝盒的組件,並且可以將「轉換」布爾值傳遞給它的構造函數。儘管解決方法依賴於用例。

+0

過渡當不可不關心box實例,它只會看到由此產生的DOM變化,對吧? 我假設發生了什麼事情是盒子實例改變,由於某種原因迫使角度來取代整個div,而不僅僅是更新樣式。 也許是因爲它在ngFor中? – Murray

+0

你有這個權利。 Angular正在使用新實例重建DOM,而不是在返回新框之後更新現有DOM。 – Adam