如何在Angular 4中对动态生成的元素触发点击事件?

3
我正在使用API get调用从数据库中获取HTML代码并呈现HTML。
生成的HTML如下:-
<span (click)="triggerClick()" data-link-id="960" data-link="8" class="level_modal">individuals</span>

triggerClick()函数在ts文件中定义,但是使用动态生成的html代码时没有触发该函数。

2个回答

2

原因

这样不行。你用来编写Angular模板的语言并不是HTML,而是一种自定义的Angular语法,它有意地看起来像HTML,以便更好地编写代码。然后这些模板被编译成高度优化的JavaScript函数。

你从API获取的字符串是在应用程序运行时接收到的,这意味着Angular的编译器已经完成了它的工作(它已经编译了代码,这就是为什么你可以运行你的应用程序)。此时,默认情况下无法再使用Angular的编译器。将编译器包含在应用程序的最终捆绑包中会导致性能问题,因为编译器代码具有较大的大小占用。这就是为什么AOT编译(提前编译)是发布Angular应用程序的默认和推荐方式的原因。

解决方案

你的API根本不应该返回HTML。单页应用程序(SPA)背后的整个思想是让它们消耗一个与语言和平台无关的API。它只是使用数据,今天的数据通常使用JSON符号编码。这是API应该理解的唯一语言。

从你在这里发布的代码示例中我可以看出,你对这种形式的数据感兴趣:

{ linkId: 960,
  link: 8,
  text: individuals }

创建一个API端点,以此形式返回数据,并使用Angular循环遍历数据并创建所需的模板。
<span *ngFor="let item of items"
       (click)="triggerClick()"
       [attr.data-link-id]="item.linkId"
       [attr.data-link]="item.link"
       class="level_modal">
  {{ item.text }}
</span>

当然,你可能并不需要所有这些data-属性。这是因为Angular应用程序应该专注于模型。模型是真相的源泉,用于创建模板。如果您需要有关每个项目的其他信息(例如linklinkId),只需将其保存在内存中作为对象即可。无需将其编码到HTML中以便稍后再次阅读。


我无法这样做,因为我是使用 API 生成完整的 HTML,并将 HTML 存储在数据库中。我该如何再次解析此生成的 HTML,以便 Angular 捕捉我的 onclick 函数? - Anmol G
没有直接的答案。你可以编写自己的定制解析器,但那很傻。你应该简单地改变你的API。 - Lazar Ljubenović

1
当你写下

(click)="doSomething()"

你想说的是:

当我点击这个时,启动 doSomething 方法

但实际上你所说的是:

请 Angular 编译这段代码,以便当我点击这个时,启动 doSomething 方法

因为你可能知道,你正在编写 Typescript,而不是 Javascript。因此,你的代码将被编译为服务,从而将其转换为:

onclick="doSomething()"

但是,等等,还有更多

当您编译代码时,实际上会进行缩小和混淆。因此,这将为您提供类似以下内容的东西

onclick="a()"

因此,使您失去了对此的任何逻辑。

那么解决方案是什么?

解决方案是将点击事件绑定到全局函数。有两种方法可以做到这一点:

  • 在组件中使用函数(如果要使用组件中的逻辑,请使用此方法
  • 全局函数(如果要在多个组件中调用此函数,请使用此方法

我将解释第一种用例,对于第二种用例,我会简单介绍:创建一个JS文件作为资产,将您的函数放入其中,并在单击时调用它。

对于第二个问题,有点棘手。

首先,在您的组件中注入ngZone:这允许您处理Angular之外的代码。

constructor(private zone: NgZone) {}

然后,创建一个全局函数(我将使用TypeScript并符合linting规范)

ngOnInit() {
  this.zone.run(() => {
    window['doSomething'] = () => {
      console.log('Look mom, I did something !');
    };
  });
}

离开组件后,请删除该函数。
ngOnDestroy() { delete(window['doSomething']); }

最后,将您的HTML代码从这个样子改为:

(click)="doSomething()"

To this

onclick="window.doSomething()"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接