如何为Angular 4动态创建的div绑定(click)点击事件
解决Angular动态创建元素绑定点击事件的问题
这个问题我之前也碰到过!原因很简单:你用字符串拼出来的HTML,Angular根本没机会编译它,所以(click)这种Angular专属的绑定语法对它来说就是普通文本,完全不会和你的组件方法关联起来。下面给你几种靠谱的解决办法,按推荐程度排序:
1. 优先用Angular模板语法(最推荐)
Angular的设计初衷就是用声明式模板来处理动态内容,完全没必要手动拼接HTML字符串。比如如果是根据数据列表生成节点,直接用*ngFor就行:
<!-- 在组件模板里编写 --> <div *ngFor="let item of yourDataList" class="node" [id]="item.id"> <div class="divcl"> <i class="fa fa-refresh" [id]="item.id" (click)="addTab($event)"></i> </div> </div>
这样Angular会自动编译每一个生成的元素,(click)绑定自然就生效了,代码可读性和维护性都比手动拼字符串高太多。
2. 用Renderer2手动创建元素并绑定事件(适合复杂场景)
如果因为某些特殊需求必须手动创建DOM元素,别直接操作原生DOM,用Angular提供的Renderer2工具,它能帮你安全地操作DOM,还能自动处理组件销毁时的事件清理:
首先在组件里注入Renderer2和ElementRef:
import { Component, Renderer2, ElementRef } from '@angular/core'; @Component({ // 组件元数据配置 }) export class YourComponent { constructor(private renderer: Renderer2, private el: ElementRef) {} createDynamicNode() { // 创建外层node div const nodeDiv = this.renderer.createElement('div'); this.renderer.addClass(nodeDiv, 'node'); this.renderer.setAttribute(nodeDiv, 'id', this.data.id); // 创建内层divcl div const divclDiv = this.renderer.createElement('div'); this.renderer.addClass(divclDiv, 'divcl'); // 创建图标元素 const icon = this.renderer.createElement('i'); this.renderer.addClass(icon, 'fa'); this.renderer.addClass(icon, 'fa-refresh'); this.renderer.setAttribute(icon, 'id', this.data.id); // 绑定点击事件,直接关联组件的addTab方法 this.renderer.listen(icon, 'click', (event) => { this.addTab(event); }); // 组装元素层级 this.renderer.appendChild(divclDiv, icon); this.renderer.appendChild(nodeDiv, divclDiv); // 把最终的元素添加到页面的目标容器里(比如组件的根元素) this.renderer.appendChild(this.el.nativeElement, nodeDiv); } }
3. 原生DOM事件绑定(不推荐,仅作应急)
如果你实在要保留字符串拼接的方式,也可以用原生的addEventListener,但要注意上下文的问题,还要记得在组件销毁时移除事件监听,防止内存泄漏:
// 先通过ViewChild获取目标容器 @ViewChild('container') container!: ElementRef; createDynamicNode() { const addOns = `<div class="divcl"><i class="fa fa-refresh" id="${this.data.id}"></i></div>`; const nodeHtml = `<div class='node' id='${this.data.id}'>${addOns}</div>`; // 插入HTML到容器 this.container.nativeElement.innerHTML = nodeHtml; // 找到图标元素并绑定事件 const icon = this.container.nativeElement.querySelector(`#${this.data.id}`); if (icon) { // 用箭头函数确保this指向当前组件实例 icon.addEventListener('click', (event) => this.addTab(event)); } } // 组件销毁时移除事件监听 ngOnDestroy() { const icon = this.container.nativeElement.querySelector(`#${this.data.id}`); if (icon) { icon.removeEventListener('click', this.addTab); } }
总的来说,尽量用前两种方法,尤其是第一种模板语法,完全符合Angular的设计理念,踩坑的概率也最低。
内容的提问来源于stack exchange,提问作者Ronak Gupta
相关产品推荐
相关产品推荐

