Динамическое добавление прослушивателя событий в Angular 2
Я только начинаю возиться с Angular 2, и мне интересно, может ли кто-нибудь сказать мне лучший способ динамического добавления и удаления прослушивателей событий из элементов.
у меня есть настроенный компонент. При нажатии на определенный элемент в шаблоне я хочу добавить прослушиватель для mousemove к другому элементу того же шаблона. Затем я хочу удалить этот прослушиватель при нажатии на третий элемент.
Я вроде как получил эту работу, просто используя простой Javascript, чтобы захватить элементы и затем вызов стандарта addEventListener() но мне было интересно, есть ли еще"Angular2.0" способ сделать это, что я должен смотреть.
спасибо за любые советы :)
3 ответов:
рендер был осужден в угловой 4.0.0-радиоуправляемый.1, Прочитайте обновление ниже
The angular2 way использовать
listenилиlistenGlobalС рендерернапример, если вы хотите добавить событие click к компоненту, вы должны использовать Renderer и ElementRef (это дает вам также возможность использовать ViewChild или все, что извлекает
nativeElement)constructor(elementRef: ElementRef, renderer: Renderer) { // Listen to click events in the component renderer.listen(elementRef.nativeElement, 'click', (event) => { // Do something with 'event' }) );можно использовать
listenGlobalчто будет дать вам доступ кdocument,bodyи т. д.renderer.listenGlobal('document', 'click', (event) => { // Do something with 'event' });обратите внимание, что с бета-версии.2 как
listenиlistenGlobalвозвращает функцию для удаления прослушивателя (см. последние изменения раздел из журнала изменений для бета-версии.2). Это делается во избежание утечек памяти в больших приложениях (см. #6686).поэтому, чтобы удалить прослушиватель, который мы добавили динамически, мы должны назначить
listenилиlistenGlobalк переменной, которая будет содержать возвращенную функцию, а затем мы выполняем оно.// 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.С помощью RendererV2 с угловой 4.0.0-rc.1+ (Renderer2 с 4.0.0-rc.3)
25/02/2017:
Rendererбыл осужден, теперь мы должны использовать(см. строку ниже). Смотрите commit.RendererV210/03/2017:
RendererV2была переименована вRenderer2. Смотрите последние изменения.
RendererV2большеlistenGlobalфункции для глобальных событий (документ, тело, окно). Он имеет толькоlistenфункция, которая обеспечивает обе функции.для справки, я копирую и вставляю исходный код рендерера DOM реализация, так как она может измениться (да, это угловой!).
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; }как вы можете видеть, теперь он проверяет, передаем ли мы строку (документ, тело или окно), и в этом случае он будет использовать внутренний
Я Асо нахожу это чрезвычайно запутанным. как указывает @EricMartinez Renderer2 listen () возвращает функцию для удаления слушателя:
ƒ () { return element.removeEventListener(eventName, /** @type {?} */ (handler), false); }если я добавляю слушателя
this.listenToClick = this.renderer.listen('document', 'click', (evt) => { alert('Clicking the document'); })Id ожидайте, что моя функция выполнит то, что я намеревался, а не полную противоположность, которая удаляет слушателя.
// I´d expect an alert('Clicking the document'); this.listenToClick(); // what you actually get is removing the listener, so nothing...в данном сценарии Itd на самом деле имеет больше смысла называть его так:
// Add listeners let unlistenGlobal = this.renderer.listen('document', 'click', (evt) => { console.log('Clicking the document', evt); }) let removeSimple = this.renderer.listen(this.myButton.nativeElement, 'click', (evt) => { console.log('Clicking the button', evt); });должна быть веская причина для этого, но в моем мнение его очень обманчиво и не интуитивно.
вот мое решение:
я создал библиотеку с угловой 6. Я добавил общий компонент
commonlib-header, который используется как в наружном применении.Примечание
serviceReferenceкоторый класс (вводится в компонентconstructor(public serviceReference: MyService)используетcommonlib-header), который содержитstringFunctionNameспособ:<commonlib-header [logo]="{ src: 'assets/img/logo.svg', alt: 'Logo', href: '#' }" [buttons]="[{ index: 0, innerHtml: 'Button', class: 'btn btn-primary', onClick: [serviceReference, 'stringFunctionName', ['arg1','arg2','arg3']] }]"> </common-header>компонент библиотеки запрограммирован следующим образом. Динамическое событие добавляется в
onClick(fn: any)способ:export class HeaderComponent implements OnInit { _buttons: Array<NavItem> = [] @Input() set buttons(buttons: Array<any>) { buttons.forEach(navItem => { let _navItem = new NavItem(navItem.href, navItem.innerHtml) _navItem.class = navItem.class _navItem.onClick = navItem.onClick // this is the array from the component @Input properties above this._buttons[navItem.index] = _navItem }) } constructor() {} ngOnInit() {} onClick(fn: any){ let ref = fn[0] let fnName = fn[1] let args = fn[2] ref[fnName].apply(ref, args) }многоразовая
header.component.html:<div class="topbar-right"> <button *ngFor="let btn of _buttons" class="{{ btn.class }}" (click)="onClick(btn.onClick)" [innerHTML]="btn.innerHtml | keepHtml"></button> </div>
Comments