动态添加事件监听器 [英] Dynamically add event listener
问题描述
我刚刚开始使用Angular 2,我想知道是否有人可以告诉我从元素动态添加和删除事件侦听器的最佳方法。
I am just starting to mess around with Angular 2 and I wonder if anyone can tell me the best way to dynamically add and remove event listeners from elements.
I有一个组件设置。单击模板中的某个元素时,我想将 mousemove
的侦听器添加到同一模板的另一个元素中。然后,我想在单击第三个元素时删除该侦听器。
I have a component set up. When a certain element in the template is clicked I want to add a listener for mousemove
to another element of the same template. I then want to remove this listener when a third element is clicked.
我有点用普通的Javascript抓取元素然后调用标准的 addEventListener()
,但我想知道是否还有一种我应该研究的 Angular2.0 方法。
I kind of got this working just using plain Javascript to grab the elements and then calling the standard addEventListener()
but I wondered if there was a more "Angular2.0" way of doing this that I should be looking into.
推荐答案
Renderer已在Angular 4.0.0-rc.1中弃用,请阅读以下更新
angular2方式是使用 listen
或 listenGlobal
来自渲染器
例如,如果要向组件添加click事件,则必须使用Renderer和ElementRef(这也使您可以选择使用ViewChild或检索 nativeElement
)
For example, if you want to add a click event to a Component, you have to use Renderer and ElementRef (this gives you as well the option to use ViewChild, or anything that retrieves the nativeElement
)
constructor(elementRef: ElementRef, renderer: Renderer) {
// Listen to click events in the component
renderer.listen(elementRef.nativeElement, 'click', (event) => {
// Do something with 'event'
})
);
您可以使用 listenGlobal
访问文档
, body
等。
renderer.listenGlobal('document', 'click', (event) => {
// Do something with 'event'
});
请注意,自beta.2以来,都收听
和 listenGlobal
返回删除监听器的函数(请参见更改更改部分)。这是为了避免大型应用程序中的内存泄漏(请参阅#6686 )。
Note that since beta.2 both listen
and listenGlobal
return a function to remove the listener (see breaking changes section from changelog for beta.2). This is to avoid memory leaks in big applications (see #6686).
因此,要删除动态添加的监听器,必须分配 listen
或 listenGlobal
到将保存返回的函数的变量,然后我们执行它。
So to remove the listener we added dynamically we must assign listen
or listenGlobal
to a variable that will hold the function returned, and then we execute it.
// listenFunc will hold the function returned by "renderer.listen"
listenFunc: Function;
// globalListenFunc will hold the function returned by "renderer.listenGlobal"
globalListenFunc: Function;
constructor(elementRef: ElementRef, renderer: Renderer) {
// We cache the function "listen" returns
this.listenFunc = renderer.listen(elementRef.nativeElement, 'click', (event) => {
// Do something with 'event'
});
// We cache the function "listenGlobal" returns
this.globalListenFunc = renderer.listenGlobal('document', 'click', (event) => {
// Do something with 'event'
});
}
ngOnDestroy() {
// We execute both functions to remove the respectives listeners
// Removes "listen" listener
this.listenFunc();
// Removs "listenGlobal" listener
this.globalListenFunc();
}
这里是 plnkr 并提供示例。该示例包含 listen
和 listenGlobal
的用法。
Here's a plnkr with an example working. The example contains the usage of listen
and listenGlobal
.
-
2017年2月25日:已弃用
Renderer
,现在我们应该使用RendererV2
25/02/2017:
Renderer
has been deprecated, now we should use(see line below). See the commit.RendererV2
2017年3月10日: RendererV2
重命名为 Renderer2
。请参见重大更改。
10/03/2017: RendererV2
was renamed to Renderer2
. See the breaking changes.
RendererV2
没有 listenGlobal
函数用于全局事件(文档,正文,窗口)。它只有一个 listen
函数,可以同时实现这两个功能。
RendererV2
has no more listenGlobal
function for global events (document, body, window). It only has a listen
function which achieves both functionalities.
作为参考,我在这里复制&粘贴 DOM Renderer实现的源代码,因为它可能会更改(是的,这是有角度的!)。
For reference, I'm copy & pasting the source code of the DOM Renderer implementation since it may change (yes, it's angular!).
listen(target: 'window'|'document'|'body'|any, event: string, callback: (event: any) => boolean):
() => void {
if (typeof target === 'string') {
return <() => void>this.eventManager.addGlobalEventListener(
target, event, decoratePreventDefault(callback));
}
return <() => void>this.eventManager.addEventListener(
target, event, decoratePreventDefault(callback)) as() => void;
}
如您所见,现在它可以验证我们是否要传递字符串(文档,正文或窗口),在这种情况下,它将使用内部 addGlobalEventListener
函数。在任何其他情况下,当我们传递元素(nativeElement)时,它将使用简单的 addEventListener
As you can see, now it verifies if we're passing a string (document, body or window), in which case it will use an internal addGlobalEventListener
function. In any other case, when we pass an element (nativeElement) it will use a simple addEventListener
来删除监听器与在2.x中使用 Renderer
相同。 listen
返回一个函数,然后调用该函数。
To remove the listener it's the same as it was with Renderer
in angular 2.x. listen
returns a function, then call that function.
// Add listeners
let global = this.renderer.listen('document', 'click', (evt) => {
console.log('Clicking the document', evt);
})
let simple = this.renderer.listen(this.myButton.nativeElement, 'click', (evt) => {
console.log('Clicking the button', evt);
});
// Remove listeners
global();
simple();
plnkr 和 Angular 4.0.0-rc.1 ,并使用 RendererV2
plnkr 和 Angular 4.0.0-rc.3 使用 Renderer2
这篇关于动态添加事件监听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!