【问题标题】:Ionic 2: Error Expression has changed after it was checkedIonic 2:检查后错误表达式已更改
【发布时间】:2017-06-23 19:11:32
【问题描述】:

我已阅读 this answerthis answerthis answer(以及许多其他内容),但我不明白如何以我的方式解决此错误。

基本上,我正在制作一个事件倒数计时器,精确到秒。每个事件显示最大的剩余时间两次,(即 1 年 2 个月。4 天 12 小时。10 分 25 秒)。

我在屏幕上有很多事件,都调用同一个函数。如果我有一些显示秒数的倒计时,我会随机收到此错误Error Expression has changed after it was checked(有时当时间以分钟为单位时,我也会收到此错误)。

我的 html 看起来像这样:

<ion-header>
    <ion-navbar>
        <ion-title>
            <h2>{{theTime}}</h2>
        </ion-title>
    </ion-navbar>
</ion-header>

<ion-content padding-top padding-bottom>
    <ion-fab right bottom>
        <button ion-fab color="primary" (click)='goToEventUpsert()'>
            <ion-icon name="add"></ion-icon>
        </button>
    </ion-fab>
    <ion-card class="event" *ngFor="let event of events | OrderBy : 'dateTimeEpoch'" id="id-{{event.id}}">
        <div class="event__container">
            <div class="event__container__countdown" color="light" [innerHTML]="timeUntil(event.dateTime)"></div>
        <div class="event__container__details">
            ...
        </div>
    </ion-card>
</ion-content>

打字稿是这样的:

export class HomePage {
    constructor(...) {
        this.getCurrentTime();
        setInterval(() => this.getCurrentTime(), 100);
    }

    getCurrentTime() {
        this.theTime = moment().format("h:mm a");
    }

    timeUntil(date) {
        var dur = moment.duration( moment(date).diff(moment()) );
        let yearsRemain = dur.years();
        let monthsRemain = dur.months();
        let daysRemain = dur.days();
        let hoursRemain = dur.hours();
        let minutesRemain = dur.minutes();
        let secondsRemain = dur.seconds();

        var dateArray = [
            yearsRemain,
            monthsRemain,
            daysRemain,
            hoursRemain,
            minutesRemain,
            secondsRemain
        ]

        for(var i = 0; i < dateArray.length; i++) {
            if(dateArray[i] > 0){
                var firstDur = dateArray[i] + this.typeOfTime(i, dateArray[i]);
                var secondDur = dateArray[i+1] !== 0 ? dateArray[i+1] + this.typeOfTime(i+1, dateArray[i+1]) : dateArray[i+2] + this.typeOfTime(i+2, dateArray[i+2]);
                return firstDur +  secondDur;
            } else if(dateArray[i] < 0) {
                return (dateArray[i] * (-1)) + this.typeOfTime(i, (dateArray[i] * (-1))) + " ago";
            } else {
                i++
            }
        }
    }

    typeOfTime(type, num) {
        var display;
        var plur = num === 1 ? "" : "s";
        switch(type) {
            case 0:
                display = "Year" + plur;
                break;
            case 1:
                display = "Month" + plur;
                break;
            case 2:
                display = "Day" + plur;
                break;
            case 3:
                display = "Hour" + plur;
                break;
            case 4:
                display = "Minute" + plur;
                break;
            case 5:
                display = "Second" + plur;
                break;
        }
        return display;
    }
}

所以,正如我所说,我阅读了答案,但我不明白。谁能帮我解释一下?

【问题讨论】:

  • 当您在开发模式下使用 Angular 时,它会仔细检查变量的状态。尝试运行生产版本,看看有什么不同,但你应该更改不断变化的代码来解决这个问题。似乎是你的 timeUntil 函数。
  • @camaron,据我所知,这也是我所理解的。虽然我对enableProdMode() 以及把它放在哪里一头雾水。
  • 这个想法是使用 --prod 标志,如 ionic run android --prod,这将添加 enableProdMode()。但是您可以尝试在 boostrap 调用之前在 main.ts 文件中添加 enableProdMode()
  • @camaron,谢谢!我刚刚尝试过,但现在我的 SQLite 功能出现了另一个错误/问题......另一个需要研究的问题!
  • 编码愉快!我为功能读者添加了答案。

标签: javascript angularjs typescript ionic2


【解决方案1】:

好吧,我想通了,虽然我不能 100% 确定原因。

正如我在上面所写的,我使用 angular 来显示 return 值,使用 [innerHTML]。由于某种原因(这部分我不知道为什么),数据绑定无法处理“返回”值,而是需要接受一个简单的变量。我已经把它从

<div class="event__container__countdown" color="light" [innerHTML]="timeUntil(event.dateTime)"></div>

函数timeUntil() 使用返回来显示我想要的:return firstDur + secondDur;

<div class="event__container__countdown" color="light">
    {{timePrimary}} {{timePrimaryType}} {{timeSecondary}} {{timeSecondaryType}}
</div>

在哪里,我在 setTimeout 内触发我的 timeUntil() 函数(始终运行)并更改变量。

timePrimary: number;
timePrimaryType: string;
timeSecondary: number;
timeSecondaryType: string;

constructor() {
    this.timeUntil(this.timeUntilValue);
    setInterval(_ => this.timeUntil(this.timeUntilValue));
}
timeUntil(date) {

    //...All the same variable declarations...

    for(var i = 0; i < dateArray.length; i++) {
        if(dateArray[i] > 0){
            this.timePrimary = dateArray[i];
            this.timePrimaryType = this.typeOfTime(i, dateArray[i]);
            this.timeSecondary = dateArray[i+1] !== 0 ? dateArray[i+1] : dateArray[i+2];
            this.timeSecondaryType = dateArray[i+1] !== 0 ? this.typeOfTime(i+1, dateArray[i+1]) : this.typeOfTime(i+2, dateArray[i+2]);
            break;
        } else if(dateArray[i] < 0) {
            this.timePrimary = dateArray[i] * (-1);
            this.timePrimaryType = this.typeOfTime(i, (dateArray[i] * (-1))) + " ago";
            break;
        } else {
            i++
        }
    }
}

因此,出于某种原因,在这种情况下,返回一个值而不是将该值设置为一个变量是不好的。

【讨论】:

    【解决方案2】:

    当您在 开发模式 中使用 Angular 时,它会仔细检查变量的状态。 尝试运行生产版本,看看有什么不同,但你应该更改不断变化的代码来解决这个问题。 似乎是你的 timeUntil 函数。

    要在生产模式下运行,想法是使用--prod 标志,如ionic run android --prod,这将添加enableProdMode()

    但您可以尝试在main.ts 文件中添加enableProdMode(),然后再调用boostrap

    这将解决这个问题,但正如我已经说过的,这不是最好的方法。

    【讨论】:

      猜你喜欢
      • 2016-12-24
      • 2016-10-19
      • 2017-05-08
      • 2018-05-11
      • 2017-07-08
      • 1970-01-01
      • 2019-05-14
      • 2019-01-13
      • 2018-05-10
      相关资源
      最近更新 更多