Angular2 中的更改不会更新视图 [英] View is not updated on change in Angular2
问题描述
我已经开始探索 Angular2(我将使用 Angular1 和一些 React 背景)但我遇到了一个问题.
我想将某些击键绑定到组件中的操作,因此我决定使用 Angular2 生命周期来绑定/取消绑定操作.
但是,如果我从 Mousetrap 回调中执行某些操作,它可以工作,但不会呈现并且在运行摘要循环之前更改不可见.
我是否需要显式运行某些东西来更新视图
有人能帮我弄清楚发生了什么吗?任何帮助将不胜感激.
<小时>从'angular2/core'导入{Component};const 捕鼠器 = require('捕鼠器');@成分({模板:`视频模板:模式{{模式}}<input type="number" [(ngModel)]="mode"/>`})导出类视频{公共模式:号码;构造函数(){this.mode = 0;}ngOnInit() {console.log('你好视频组件');Mousetrap.bind('d', () => console.log('this.mode=', this.mode));Mousetrap.bind('i', () => this.incrementMode());//不起作用this.incrementMode();//有效this.incrementMode();//有效setTimeout(() => this.incrementMode(), 4000);//有效}增量模式(){console.log('incMode', this.mode++);};ngOnDestroy() {console.log('再见视频组件');Mousetrap.unbind(['d', 'i']);}}
虽然@Günter 的回答绝对正确,但我想提出一个不同的解决方案.
Mousetrap
库的问题在于它在 angular "noreferrer">区域(参见 这里).但是要在每个异步事件之后触发更改检测,应该在 angular zone>.您有两种选择来实现这一目标:
- 使用依赖注入:
bootstrap(App, [provide(Mousetrap, { useFactory: () => new Mousetrap() }) ]);//...@成分({选择器:'我的应用',//...})出口类应用{构造函数(@Inject(Mousetrap)捕鼠器){this.mousetrap = 捕鼠器;//...}//...}
- 只需在构造函数中创建
Mousetrap
的实例:
@Component({选择器:'我的应用',//...})出口类应用{构造函数(){this.mousetrap = new Mousetrap();//...}//...}
在这两种情况下,您都可以像这样使用捕鼠器实例:
ngOnInit() {this.mousetrap.bind('i', () => this.incrementMode());//现在可以了!!!//...}
现在你不需要在每个bind
调用中使用ngZone.run()
.在依赖注入的情况下,您还可以在应用程序的任何组件/服务中使用此 mousetrap
实例(不仅在 App
组件中).
请参阅这个 plunk.我在那里使用依赖注入.
I've started exploring Angular2 (I'm coming with Angular1 and a bit of React background) and I got stuck with a problem.
I want to bind certain keystrokes to actions in my component, so I've decided to use Angular2 lifecycle to bind/unbind actions.
However, if I do something from within a Mousetrap callback, it works, but it's not rendered and a change is not visible until a digest cycle is run.
Do I need to run something explicitly to update a view
Could somebody help me to figure out what is going on? Any help would be very appreciated.
import {Component} from 'angular2/core';
const Mousetrap = require('mousetrap');
@Component({
template: `<div>
Video template: Mode {{ mode }}
<input type="number" [(ngModel)]="mode"/>
</div>`
})
export class Video {
public mode: number;
constructor() {
this.mode = 0;
}
ngOnInit() {
console.log('hello Video component');
Mousetrap.bind('d', () => console.log('this.mode=', this.mode));
Mousetrap.bind('i', () => this.incrementMode()); // doesn't work
this.incrementMode(); // works
this.incrementMode(); // works
setTimeout(() => this.incrementMode(), 4000); // works
}
incrementMode() {
console.log('incMode', this.mode++);
};
ngOnDestroy() {
console.log('bye bye Video component');
Mousetrap.unbind(['d', 'i']);
}
}
Although @Günter's answer is absolutely correct I want to propose a different solution.
The problem with Mousetrap
library is that it creates its instance outside of the angular zone (see here). But to fire change detection after each async event the instance should be instantiated inside the angular zone. You have two options to achieve this:
- Use dependency injection:
bootstrap(App, [provide(Mousetrap, { useFactory: () => new Mousetrap() }) ]);
// ...
@Component({
selector: 'my-app',
// ...
})
export class App {
constructor(@Inject(Mousetrap) mousetrap) {
this.mousetrap = mousetrap;
// ...
}
//...
}
- Just create instance of
Mousetrap
inside of the constructor:
@Component({
selector: 'my-app',
// ...
})
export class App {
constructor() {
this.mousetrap = new Mousetrap();
// ...
}
//...
}
In both cases you will have the ability to use the mousetrap instance like this:
ngOnInit() {
this.mousetrap.bind('i', () => this.incrementMode()); // It works now!!!
// ...
}
Now you don't need to use ngZone.run()
in every bind
call. In case of dependency injection you also can use this mousetrap
instance in any component/service of your application (not only in App
component).
See this plunk. I use dependency injection there.
这篇关于Angular2 中的更改不会更新视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!