【问题标题】:Angular2 pipe causing '...has changed after it was checked' dev errorAngular2 管道导致“...检查后已更改”开发错误
【发布时间】:2016-04-23 14:14:10
【问题描述】:

我知道为什么会抛出这个错误,但我不明白如何组织我的代码来修复它。问题来了

@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 管道

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

所以文章组件使用工具栏数组传递到的工具栏组件,这反过来又使用可见管道过滤掉可见属性设置为false的项目。

VisiblePipe 管道运行时,会抛出错误。那么由于某种原因,管道转换代码在更改检测之后运行?为什么?

编辑

所以我根据 Gunter 的建议更新了我的 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
}

这真的是最好/唯一的方法吗?感觉就像我自己在处理变更检测的某些方面!

【问题讨论】:

    标签: typescript angular


    【解决方案1】:

    该错误是因为在devMode Angular 中每转运行两次更改检测,并且即使输入值没有更改,您的管道也会为两个后续调用返回不同的数组实例。 当设置为 pure: false 时,这甚至不是“允许的”。

    要修复它,请确保您的管道在输入未更改时为后续调用返回相同的数组实例。

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

    如果可以从外部修改数组(无需创建新实例),那么您也需要注意这一点。然后您需要检查自上次调用以来数组的内容是否发生了变化。

    您可以使用IterableDiffers 检查数组中的项目是否被添加、删除或替换。 这仍然不包括数组中包含的项目的属性更改。

    【讨论】:

    • 这个表达式是什么this cached; 是错字还是正常?
    • 我想在cached的任何地方都应该是resultCached
    • 我认为this.cached 应该是this.value(已修复),但我很久以前就研究过这个......抱歉造成混乱。
    猜你喜欢
    • 2016-04-01
    • 2016-04-30
    • 2016-06-13
    • 2017-06-08
    • 2017-12-01
    • 1970-01-01
    • 2017-06-26
    • 1970-01-01
    相关资源
    最近更新 更多