【问题标题】:How to access component class variables inside a callback function in angular?如何以角度访问回调函数内的组件类变量?
【发布时间】:2020-05-12 10:18:01
【问题描述】:

在我的组件中,我使用 addEventListener 订阅了 html 点击事件,并传递了回调函数。在回调函数中,我使用了类似 this.someVariable 的组件变量,但我看到 this 的范围已更改并设置为 html 元素对象。在这里如何使用组件变量?下面我给出了一个示例代码。在我的handleHtmlClickEvent() 函数中,我无法访问this.x 变量。

export class SomeComponent implements OnInit, AfterViewInit{
   x = 'Hello';
   constructor(private elementRef: ElementRef){}
   ngOnInit(){
   }
   ngAfterViewInit(){
     const element = this.elementRef.nativeElement.getByElementId('123');
     element.addEventListener('click', this.handleHtmlClickEvent)
   }
   handleHtmlClickEvent(){
     console.log(this.x);
   }
}

【问题讨论】:

  • 这是角度 2 吗? (使用打字稿)。如果是,有更好的方法来做到这一点
  • 角度 7。你能解释一下@SupunDeSilva 的方式吗?
  • 对不起,我错过了消息,我会采取@ionut-t 的方法检查链接stackblitz.com/edit/angular-ivy-uj1ete

标签: javascript angular typescript dom-events


【解决方案1】:

不要直接接触 DOM。这样做是不好的做法。

使用ViewChild 装饰器或创建指令。

解决方案 1 - ViewChild

在您的 html 模板中,将模板变量分配给您要定位的元素:

<div #element></div>

在您的组件中:

export class SomeComponent implements OnInit, AfterViewInit{
   x = 'Hello';
   @ViewChild('element') element: ElementRef<HTMLDivElement>;

   // use @HostListener decorator to attach your listener
   @HostListener('click', ['$event'])
   onClick(event: MouseEvent) {
    if (event.target === this.element.nativeElement) {
      console.log(this.x);
    }
  }
}

解决方案 2 - 指令

@Directive({
  selector: '[appSomeDirective]'
})
export class SomeDirective {
   // use the Input decorator to display the message
   @Input() message: string;

   constructor(private elementRef: ElementRef){}

   @HostListener('click', ["$event"])
   onClick(event: MouseEvent) {
     console.log(this.message);
  }
}

在您的组件模板中:

<div appSomeDirective [message]="x"></div>

如果您想操作一个或多个元素,请使用Render2 服务。

更新

对于您评论中描述的情况,您可以执行以下操作:

 x = 'Hello';
 @ViewChild('element') element: ElementRef<HTMLDivElement>;

 constructor(private renderer: Renderer2) {}

 ngAfterViewInit() {
    const links = this.element.nativeElement.querySelectorAll('a');

    links.forEach(link =>
      // use the Renderer2 service to start an event listener 
      this.renderer.listen(link, 'click', (event: MouseEvent) => {
        console.log(this.x);
        ...
      })
    );
  }

虽然上面的实现可以工作,但如果你有几十个或几百个链接,我不确定它的性能如何。

【讨论】:

  • 实际上我的 html 数据是通过 api 作为字符串传入的,我在 div 中使用 innerHtml 呈现 html。重点是,我想捕捉&lt;a&gt; 标签点击事件。所以我要做的是,使用this.elementRef.nativeElement.querySelectorAll('a') 获取所有&lt;a&gt; 标签,然后在所有&lt;a&gt; 元素中添加eventListener。在这种情况下,我如何使用ViewChild 处理这个问题?
  • 感谢@ionut-t 的帮助。但问题是当我在不使用匿名函数的情况下将回调函数作为参数传递时,范围发生了变化,我无法访问this.x,正如我在问题中提到的那样。
  • @Shakibuz_Zaman 我已经忘记了这一点,但是您可以像 V_R 在他的回答中建议的那样轻松地做到这一点:links.forEach(link =&gt; this.renderer.listen(link, 'click', this.handleHtmlClickEvent.bind(this)));
  • 是的,我注意到了。顺便说一句,再次感谢您的帮助。所以我将@V_R 标记为已接受的答案,因为他首先给出了可靠的答案。我希望您将您的答案标记为已接受,但 stackoverflow 不允许将 2 个答案设为已接受:P
  • 不客气,不用担心。这是正确的做法。编码愉快!
【解决方案2】:

为您的点击事件分配范围

element.addEventListener('click', this.handleHtmlClickEvent.bind(this))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多