我在尝试(click)在Angular 2中的事件回调函数内执行某些逻辑时遇到了很大麻烦,而没有触发变化检测.
为什么我不想触发变化检测
回调函数执行简单的动画滚动到顶部.它不会影响其他任何组件,因此我不需要在每个组件中进行变化检测,实际上我真的不希望它开火!由于变化检测在每个组件中都会触发,因此动画在移动设备上的性能极差.
我试过的
我知道我可以使用区域外的代码运行
this._zone.runOutsideAngular(() => {
someFunction();
})
Run Code Online (Sandbox Code Playgroud)
这很好地工作,当你想向区外运行的代码不是由调用click,keyup,keydown事件等.
因为我的组件看起来像......
<button (click)="doThing()">Do that thing outside the zone!</button>
doThing() {
this._zone.runOutsideAngular(() => {
myFunction();
})
}
Run Code Online (Sandbox Code Playgroud)
... myFunction将在区域外运行,但click事件将触发变化检测.
我已经OnPush在尽可能多的组件中实现了变更检测策略.
重要的是,此处不会触发更改检测,但我找不到阻止它的方法.
编辑
请参见此plnk,并OnPush在所有组件中设置更改检测.单击子行组件按钮会在子行,行和应用程序组件中触发CD.
我使用的workingData服务包含渗透到我的应用程序的数据.它向Mock workingData对象返回一个observable .
@Injectable()
export class WorkingDataService {
getWorkingData(): Observable<WorkingData> {
return Observable.of(WORKINGDATA);
}
getSelectedDate(): Observable<Date> {
return Observable.of(WORKINGDATA.selectedDate);
}
}
Run Code Online (Sandbox Code Playgroud)
workingData对象上的一个属性是名为的日期字段selectedDate.
export const WORKINGDATA: WorkingData = {
today: new Date(),
selectedDate: new Date('11-15-2016'),
targetDate: new Date(),
data: []
};
Run Code Online (Sandbox Code Playgroud)
这会incrementDate()在cal-nav组件中触发以下函数(或它的对应函数):
decrementDate(): void {
let newDate = new Date(this.workingData.selectedDate.getDate());
newDate.setMonth(newDate.getMonth() - 1);
this.workingData.monthPrior = newDate;
}
Run Code Online (Sandbox Code Playgroud)
observable更新了workingDate注入服务的所有comopnents中的视图,但我现在需要在month组件中触发一个funtion (这是组件的兄弟cal-nav).每次更新组件中的某个功能是如何更新的,即使它是从另一个组件更新的?month …
javascript observable typescript angular2-changedetection angular
这是一个例子:
@Component({
selector: 'my-app',
template: `
<div>
<h1>{{ foo }}</h1>
<bpp [(foo)]="foo"></bpp>
</div>
`,
})
export class App {
foo;
}
@Component({
selector: 'bpp',
template: `
<div>
<h2>{{ foo }}</h2>
</div>
`,
})
export class Bpp {
@Input('foo') foo;
@Output('fooChange') fooChange = new EventEmitter();
ngAfterViewInit() {
const potentiallyButNotNecessarilyAsyncObservable = Observable.of(null);
potentiallyButNotNecessarilyAsyncObservable.subscribe(() => {
this.fooChange.emit('foo');
})
}
}
Run Code Online (Sandbox Code Playgroud)
偶尔出现错误的地方:
ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后发生了变化.上一个值:'undefined'.当前价值:'foo'
这是因为双向绑定由一个可以获得相同tick上的值的observable更新.我宁愿不用上面的逻辑包装,setTimeout因为它看起来像一个hack并使控制流复杂化
在这里可以做些什么来避免这个错误?
是否ExpressionChangedAfterItHasBeenCheckedError错误有不良影响还是可以忽略不计?如果可以的话,可以改变探测器是否静音并且不会污染控制台?
我在我的 Angular 应用程序中做了一个加载微调组件。我用 *ngIf="isLoading" 将它放在路由器出口旁边的应用程序组件中,这样我就可以让它在应用程序的任何地方都可见。
'isLoading' 布尔值正在使用 ngrx 的商店进行全局更新。
现在我有一个错误说
错误:ExpressionChangedAfterItHasBeenCheckedError:检查后表达式已更改。以前的值:'ngIf: true'。当前值:'ngIf:false'
我一直在阅读有关此错误的信息,结论是:不要更改更深层次的子组件的参数值。
那么如何在不重复我的应用程序中的代码并且不导致更改检测错误的情况下制作加载微调器呢?
我对变更检测和管道有疑问。我找不到解决这个问题的好方法。
我创建了一个小项目来在这里重现它。转到 /monitor 路线。
当您单击“更改”按钮时,它会更改数组中第一项的值,但 UI 不会更新。
如果我在更改处理程序中重新创建另一个对象,它会起作用
this.state[0] = Object.assign({}, this.state[0], { value: 999.99 });
Run Code Online (Sandbox Code Playgroud)
但我不想那样做。我需要保留相同的对象引用。
问题来自于vital-value.component.html中的管道
{{ _vitalValue | vitalFormat }}
Run Code Online (Sandbox Code Playgroud)
如果我使用它,它会起作用
{{ _vitalValue.value }}
Run Code Online (Sandbox Code Playgroud)
有没有办法保留管道但使刷新发生?
谢谢!
我正在尝试在我的网站上布局选项卡,并且我正在使用 md-tab-group 来实现此目的。我无法使墨迹栏处于默认状态,但是,相应选项卡上写入的内容可用。墨水栏在单击时出现,而不是在页面初始化时出现。下面是我的代码
<md-tab-group dynamicHeight = "true" >
<md-tab id="hello1" label="Tab 1">
<!-- some content here -->
</md-tab>
<md-tab id="hello2" label="Tab 2">
<!-- some content here -->
</md-tab>
</md-tab-group>
Run Code Online (Sandbox Code Playgroud)
我尝试过的解决方案是a)动态生成选项卡时selectedIndex在md-tab-group中不起作用 b)Angular Material选项卡SelectedIndex 0不起作用
知道我忽略了什么吗?
angular-material angular2-changedetection angular angular2-md-tabs
我只需要在加载组件或路由发生变化时检测一次角度变化,然后我想停止检测变化。
实际上我需要根据用户角色显示和隐藏功能。所以我*ngIf在一个 html 模板中有很多,但是我只需要在*ngIf第一次加载模板时检查一次条件,然后停止检测更改,因为它会影响性能。
我希望页面在单次更改检测后像静态一样。
例如 :
<li *ngIf="doesHavePermission('templateName')">
</li>
Run Code Online (Sandbox Code Playgroud)
应该检查一次,但我看到的是它正在多次检查单身的变化*ngIf,我有很多*ngIf这样的:
我发现markForCheck()
和detach()这个角文档中https://angular.io/api/core/ChangeDetectorRef。
但他们正在做的是他们要么允许所有更改检测,要么根本不允许,
而且我只需要检测一次更改并在此之后停止。
我们可以在角度上进行单次时间变化检测吗?
或者有更好的方法来处理场景吗?
performance typescript angular2-changedetection angular angular-changedetection
假设我在屏幕上产生了100个div,*ngFor该div的值来自对象的数据,例如
{A1: someObject, A2: someOtherObject..., J10: someOtherOtherObject}
我单击A1,然后单击J10,它们切换其值。改为:
{A1: someOtherOtherObject, A2: someOtherObject..., J10: someObject}
如何强制Angular仅刷新仅包含A1和J10值的两个div?我正在使用ChangeDetectionStrategy.OnPush,在拥有的构造函数中cd.detach(),只有cd.detectChanges()在第二次单击发生时才调用。从我所看到和能够理解的角度来看,每个div都会触发它们,*ngIf因此将重新创建每个div 。
我可以做些什么来要么a)覆盖正在刷新的内容,要么b)选择检测更改所针对的内容?
angular2-changedetection angular angular-changedetection angular7
我有一个包含日期(格式化toLocaleString())和其他东西的组件列表.在它们之上有一个用于创建新组件的组件,其中包含一个带有一些使用角色形状构建器构建的输入字段的表单.当我快速键入时,验证滞后并且我正在键入的文本不会立即显示.
我假设Angular正在重新渲染所有组件,因为如果我不在其他组件中显示日期,我可以快速键入而不会有滞后.
有没有办法只重新输入我输入的输入字段,因为所有其他组件都无法更改或是toLocaleString()问题?
我已经阅读了一些关于Change DetectionAngular 的好文章,并且对它是什么以及它是如何工作的有了一定的了解。但是到目前为止我读过的每篇文章都只关注组件上Change Detection何时发生某些事件或某些input属性更改时等。我还没有找到任何文章关注route更改时会发生什么?Change Detection在这种情况下如何工作?此外,Angular 是一次性将所有 HTML/DOM 更新推送到浏览器,还是在发现任何 DOM 更新后立即不断向浏览器提供信息?
angular ×10
typescript ×4
javascript ×2
performance ×2
angular-pipe ×1
angular7 ×1
dom ×1
observable ×1
routes ×1
zonejs ×1