Sine Python 3.5 вы можете использовать функцию math.isclose()
, если условия
import math
if math.isclose(0.1 + 0.2, 0.3, abs_tol=0.01):
pass
Во-первых, обратите внимание, что это исключение будет генерироваться только при запуске вашего приложения в режиме dev (что по умолчанию имеет значение по умолчанию в бета-0): Если вы вызываете enableProdMode()
при загрузке приложения он не будет сброшен ( см. обновленный plunk ).
Во-вторых, не делайте этого, потому что это исключение генерируется по уважительной причине: Короче говоря, когда в режиме dev каждый раунд обнаружения изменений сразу же сопровождается вторым раундом, который проверяет, что никакие привязки не изменились начиная с конца первого, так как это указывает на то, что изменения вызваны самим обнаружением изменения.
В вашем плунге привязка {{message}}
изменяется вашим вызовом на setMessage()
, что происходит в крюк ngAfterViewInit
, который происходит как часть начального поворота обнаружения изменений. Это само по себе не является проблематичным - проблема в том, что setMessage()
изменяет привязку, но не вызывает новый раунд обнаружения изменений, а это означает, что это изменение не будет обнаружено до тех пор, пока какой-либо другой раунд обнаружения изменений не будет запущен где-то в другом месте ,
Вынос: все, что меняет привязку, должно запускать раунд обнаружения изменений, когда это происходит.
Обновление в ответ на все запросы для примера того, как это сделать: @ Решение Tycho работает, как и три метода из , на которые указывает ответ @MarkRajcok. Но, честно говоря, все они кажутся уродливыми и неправильными для меня, такими, как хаки, которые мы привыкли опираться на ng1.
Конечно, существуют случайные обстоятельства, когда эти хаки подходят, но если вы используете их на чем-либо более, чем очень случайным образом , это признак того, что вы боретесь с каркасом, а не полностью обнимаете его реактивный характер.
ИМХО, более идиоматический подход «Угловой 2» приближается к этому, это что-то вроде: ( plunk )
@Component({
selector: 'my-app',
template: `<div>I'm {{message | async}} </div>`
})
export class App {
message:Subject<string> = new BehaviorSubject('loading :(');
ngAfterViewInit() {
this.message.next('all done loading :)')
}
}
В статье Все, что вам нужно знать о ошибке ExpressionChangedAfterItHasBeenCheckedError
, объясняет поведение в деталях.
Проблема с настройкой заключается в том, что ngAfterViewInit
выполненные после изменения обнаружения обработанных обновлений DOM. И вы эффективно меняете свойство, которое используется в шаблоне в этом хук, что означает, что DOM необходимо повторно отобразить:
ngAfterViewInit() {
this.message = 'all done loading :)'; // needs to be rendered the DOM
}
, и для этого потребуется другой цикл обнаружения изменений и угловой по дизайну (g6)
setTimeout
, Promise.then
, либо с асинхронными наблюдаемыми ссылками в шаблоне ngAfterViewChecked () работал для меня:
import { Component, ChangeDetectorRef } from '@angular/core'; //import ChangeDetectorRef
constructor(private cdr: ChangeDetectorRef) { }
ngAfterViewChecked(){
//your code to update the model
this.cdr.detectChanges();
}
Я исправил это, добавив ChangeDetectionStrategy из углового ядра.
import { Component, ChangeDetectionStrategy } from '@angular/core';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'page1',
templateUrl: 'page1.html',
})
Не можете ли вы использовать ngOnInit
, потому что вы просто изменяете переменную-член message
?
Если вы хотите получить ссылку на дочерний компонент @ViewChild(ChildComponent)
, вам действительно нужно подождать это с ngAfterViewInit
.
Грязное исправление - вызвать updateMessage()
в следующем цикле событий, например, setTimeout.
ngAfterViewInit() {
setTimeout(() => {
this.updateMessage();
}, 1);
}
Для этого я попытался ответить выше, многие из них не работают в последней версии Angular (6 или новее)
Я использую элемент управления Material, который требует изменений после первого связывания.
export class AbcClass implements OnInit, AfterContentChecked{
constructor(private ref: ChangeDetectorRef) {}
ngOnInit(){
// your tasks
}
ngAfterViewInit() {
this.ref.detectChanges();
}
}
Добавление моего ответа так, это помогает решить определенную проблему.
Вы также можете создать таймер с помощью rxjs Observable.timer, а затем обновить сообщение в своей подписке =>
Observable.timer (1) .subscribe (() => this.updateMessage ()) ;
Вам просто нужно обновить сообщение в правильном ключе жизненного цикла, в данном случае это ngAfterContentChecked
вместо ngAfterViewInit
, потому что в ngAfterViewInit была запущена проверка сообщения переменной, но еще не закончена.
см .: https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#afterview
, поэтому код будет просто:
import { Component } from 'angular2/core'
@Component({
selector: 'my-app',
template: `<div>I'm {{message}} </div>`,
})
export class App {
message: string = 'loading :(';
ngAfterContentChecked() {
this.message = 'all done loading :)'
}
}
Он выдает ошибку, потому что ваш код обновляется при вызове ngAfterViewInit (). Значение вашего начального значения изменилось, когда ngAfterViewInit имеет место. Если вы вызываете это в ngAfterContentInit (), то он не будет вызывать ошибку.
ngAfterContentInit() {
this.updateMessage();
}
Я уже пробовал это решение: (Это сработало!) [/ g1]
export class BComponent {
name = 'I am B component';
@Input() text;
constructor(private parent: AppComponent) {}
ngOnInit() {
setTimeout(() => {
this.parent.text = 'updated text';
});
}
ngAfterViewInit() {
setTimeout(() => {
this.parent.name = 'updated name';
});
}
}
Вы можете прочитать более подробно здесь: https://blog.angularindepth.com/everything-you-need -в-ноу-о-The-expressionchangedafterithasbeencheckederror-ошибок e3fd9ce7dbb4
Я не могу прокомментировать сообщение @Biranchi, так как у меня нет достаточной репутации, но она исправила проблему для меня.
Одно замечание! Если добавить changeDetection: ChangeDetectionStrategy.OnPush на компонент не работает, а его дочерний компонент (немой компонент) попробуйте добавить его к родительскому объекту.
Это исправило ошибку, но мне интересно, каковы побочные эффекты этого.
Вы также можете поместить свой вызов updateMessage () в ngOnInt () - Method, по крайней мере, он работает для меня
ngOnInit() {
this.updateMessage();
}
. В RC1 это не вызывает исключение
Как указано в drewmoore, правильным решением в этом случае является ручное инициирование обнаружения изменений для текущего компонента. Это делается с использованием метода detectChanges()
объекта ChangeDetectorRef
(импортированного из angular2/core
) или его метода markForCheck()
, который также обновляет любые родительские компоненты. Соответствующий пример :
import { Component, ChangeDetectorRef } from 'angular2/core'
@Component({
selector: 'my-app',
template: `<div>I'm {{message}} </div>`,
})
export class App {
message: string = 'loading :(';
constructor(private cdr: ChangeDetectorRef) {}
ngAfterViewInit() {
this.message = 'all done loading :)'
this.cdr.detectChanges();
}
}
Здесь также Plunkers демонстрируют ngOnInit , setTimeout и enableProdMode на всякий случай.