2016-04-23 22 views
3

我知道爲什麼會拋出這個錯誤,但我不明白如何組織我的代碼來修復它。這裏是Angular2管道在檢查後發生變化''dev error

@Pipe({ 
    name: 'visible', 
    pure: false 
}) 
export class VisiblePipe implements PipeTransform { 
    transform(value) { 
     return (<Array<any>>value).filter(v => v.visible !== false); 
    } 
} 

所以文章組件使用工具欄組件的工具欄數組傳遞問題

@Component({ 
    selector: 'article', 
    templateUrl: 'article.html', 
    moduleId: module.id, 
    directives: [Toolbar] 
}) 
export class Article { 
    public toolbar: Array<IToolbarItem>; 

    constructor() { 
     this.toolbar = [ 
      { 
       css: 'ic-save', 
       action: (item) => { }, 
       visible: false 
      }, 
      <IDropdownItem>{ 
       css: 'ic-edit', 
       items: [ 
        { 
         css: 'ic-edit', 
         label: 'Edit Article', 
         action: (item) => { } 
        }, 
        { 
         css: 'ic-edit', 
         label: 'Edit Content', 
         action: (item) => { 
          this.toolbar[0].visible = true; 
         } 
        } 
       ] 
      } 
     ]; 
    } 
} 

和工具欄組件和模板

@Component({ 
    selector: 'toolbar', 
    moduleId: module.id, 
    templateUrl: 'toolbar.html', 
    styleUrls: ['toolbar.css'], 
    pipes: [VisiblePipe], 
    encapsulation: ViewEncapsulation.None 
}) 
export class Toolbar { 
    @Input() items: Array<IToolbarItem>; 
} 

<div class="container"> 
    <div class="toolbar"> 
     <div class="toolbar-item" *ngFor="#i of (items | visible)"> 
     . 
     . 
     . 

終於VisiblePipe管,這反過來使用可見管道過濾掉可見屬性設置爲false的項目。

VisiblePipe管道運行時,會引發錯誤。所以出於某種原因,管道變換代碼在更改檢測之後運行?爲什麼?

編輯

所以我已經更新了我VisiblePipe管按照由岡特的建議,並正在

export class VisiblePipe implements PipeTransform { 
    private previousValue: Array<IVisibleItem>; 
    private cacheResult: Array<IVisibleItem>; 

    transform(value: Array<IVisibleItem>) { 
     if (!this.previousValue || !compareArrays(this.previousValue, value)) { 
      this.previousValue = value.map(i => { return { visible: i.visible } }); 
      this.cacheResult = value.filter(v => v.visible !== false); 
     } 

     return this.cacheResult; 
    } 
} 

function compareArrays(arrayOne: Array<IVisibleItem>, arrayTwo: Array<IVisibleItem>) { 
    if (arrayOne.length !== arrayTwo.length) { 
     return false; 
    } 

    for (let i = 0, l = arrayOne.length; i < l; i++) { 
     let arrayOneEntry = arrayOne[i]; 
     let arrayTwoEntry = arrayTwo[i]; 

     if (arrayOneEntry.visible !== undefined && 
      arrayTwoEntry.visible !== undefined && 
      arrayOneEntry.visible !== arrayTwoEntry.visible) { 
      return false; 
     } 
    } 

    return true; 
} 

interface IVisibleItem { 
    visible: boolean 
} 

,這真的是最好的/唯一途徑?感覺就像我正在處理變化檢測的一些方面!

回答

3

錯誤的產生是因爲在devMode Angular運行每次都會改變檢測兩次,並且管道爲兩個後續調用返回一個不同的數組實例,即使輸入值沒有改變。 當設置爲pure: false時,甚至不允許「允許」。

要修復它,確保您的管道在輸入未更改時爲相繼的調用返回相同的數組實例。

@Pipe({ 
    name: 'visible', 
    pure: false 
}) 
export class VisiblePipe implements PipeTransform { 
    this cached; 
    transform(value) { 
     if(value == this.cached && this.resultCached) { 
     return this.resultCached; 
     } 
     this.value = value; 
     this.resultCached = (<Array<any>>value).filter(v => v.visible !== false); 
     return this.resultCached; 
    } 
} 

如果可以從外部修改數組(無需創建新實例),那麼您也需要考慮到這一點。然後您需要檢查自上次調用以來數組的內容是否已更改。

您可以使用IterableDiffers來檢查數組中的項目是否被添加,刪除或替換。 這仍然不包括數組中包含項目的屬性更改。

相關問題