programing

이벤트 리스너 동적 추가

topblog 2023. 3. 4. 14:06
반응형

이벤트 리스너 동적 추가

이제 막 Angular 2를 만지작거리기 시작했는데, 이벤트 청취자를 요소에서 동적으로 추가하고 제거할 수 있는 가장 좋은 방법을 알려줄 수 있는지 궁금합니다.

컴포넌트를 설정했습니다.템플릿의 특정 요소를 클릭하면 다음 항목에 대해 청취자를 추가합니다.mousemove같은 템플릿의 다른 요소로 이동합니다.그런 다음 세 번째 요소를 클릭하면 이 수신기를 제거합니다.

플레인 Javascript를 사용하여 요소를 잡고 표준을 호출하는 것만으로 이 작업을 수행할 수 있습니다.addEventListener()'Angular2'가 더 있을까?가 조사해야 할 0" 방법.

렌더러가 Angular 4.0.0-rc.1에서 더 이상 사용되지 않습니다. 아래 업데이트를 읽어 보십시오.

angular2의 방법은listen또는listenGlobal렌더러에서

예를 들어 클릭 이벤트를 컴포넌트에 추가하려면 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'
});

beta.2 이후 두 가지 모두listen그리고.listenGlobal수신기를 제거하는 함수를 반환합니다(beta.2에 대한 changelog의 breaking changes 섹션 참조).이는 대규모 애플리케이션에서 메모리 누수를 방지하기 위한 것입니다(#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.

Angular 4.0.0-rc.1+에서의 RendererV2 사용

  • 2017년 2월 25일:Renderer는 더 이상 사용되지 않습니다(아래 행 참조).커밋을 참조해 주세요.

  • 2017년 10월 3일 :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;
  }

보시는 바와 같이 문자열(문서, 본문 또는 창)이 전달되고 있는지 확인합니다.이 경우 내부가 사용됩니다.addGlobalEventListener기능.어떤 경우에도 요소(네이티브 요소)를 전달하면 단순 요소가 사용됩니다.addEventListener

사람을 은 '듣는 사람'과 Renderer 2.listen함수를 반환하고 해당 함수를 호출합니다.

// 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();

Renderer V2를 사용한 Angular 4.0.0-rc.1plnkr

Renderer2사용한 Angular 4.0.0-rc.3plnkr

StackBlitz의 예시와 @tahiche로부터의 코멘트를 추가합니다.

반환값은 이벤트청취자를 추가한 후 삭제하는 함수입니다.이벤트 청취자가 더 이상 필요하지 않을 때는 이를 제거하는 것이 좋은 관행으로 간주됩니다. 이 할 수 .ngOnDestroy★★★★★★ 。

처음에는 혼란스러워 보일 수 있다는 것을 인정하지만, 실제로는 매우 유용한 기능입니다.아니면 어떻게 뒷처리를 할 수 있겠어요?

export class MyComponent implements OnInit, OnDestroy {

  public removeEventListener: () => void;

  constructor(
    private renderer: Renderer2, 
    private elementRef: ElementRef
  ) {
  }

  public ngOnInit() {
    this.removeEventListener = this.renderer.listen(this.elementRef.nativeElement, 'click', (event) => {
      if (event.target instanceof HTMLAnchorElement) {
        // Prevent opening anchors the default way
        event.preventDefault();
        // Your custom anchor click event handler
        this.handleAnchorClick(event);
      }
    });
  }

  public ngOnDestroy() {
    this.removeEventListener();
  }
}

StackBlitz는 앵커 요소를 클릭할 때 어떻게 동작하는지 보여 주는 기능을 제공합니다.

.
<img src="x" onerror="alert(1)"></div>
세정제가 제 역할을 하고 있다는 걸 보여주기 위해서요

이 바이올린을 켜면 같은 시체가 붙어 있는 걸 볼 수 있어요innerHTML소거하지 않고 문제를 증명해 보일 것입니다.

나는 이것이 매우 혼란스럽다고 생각한다.@EricMartinez가 Renderer2 listen()을 지적한 것처럼 리스너를 삭제하는 함수를 반환합니다.

ƒ () { return element.removeEventListener(eventName, /** @type {?} */ (handler), false); }

청취자를 추가하는 경우

this.listenToClick = this.renderer.listen('document', 'click', (evt) => {
    alert('Clicking the document');
})

듣는 사람을 제거하는 기능이 아니라 내가 의도한 것을 실행하는 기능을 기대합니다.

// I´d expect an alert('Clicking the document'); 
this.listenToClick();
// what you actually get is removing the listener, so nothing...

주어진 시나리오에서는 실제로 다음과 같은 이름을 붙이는 것이 더 합리적입니다.

// 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>

언급URL : https://stackoverflow.com/questions/35080387/dynamically-add-event-listener

반응형