gpt4 book ai didi

javascript - Angular 单击事件处理程序未触发更改检测

转载 作者:行者123 更新时间:2023-12-04 04:11:06 25 4
gpt4 key购买 nike

简单地说,我在组件的模板中有一个元素。这个元素有一个 ngIf条件和 (click)处理程序。它不是从一开始就呈现的,因为 ngIf 条件的计算结果为 false .

现在是有趣的部分:运行 的代码外 Angular 区域将该条件更改为 true , 并在执行 detectChanges 之后在更改检测器 ref 上手动,此元素被渲染并且点击处理程序 ofc 变为事件状态。

到目前为止一切似乎都还好,但问题是当 (click)回调在用户点击时运行,未触发更改检测 为组件。

这是复制品https://stackblitz.com/edit/angular-kea4wi

在那里重现它的步骤:

  • 点击米色区
  • 出现按钮,也点一下
  • 没有任何 react ,尽管消息应该出现在
  • 下方

    描述:
  • 米色区域有一个通过 addEventListener 注册的点击事件处理器,并且这个事件监听器的回调正在运行 Angular 区外 .里面有一个组件的showButton属性设置为 falsetrue我通过调用 detectChanges() 手动触发更改检测, 否则 showButton 的变化属性(property)不会被登记。代码如下所示:
    this.zone.runOutsideAngular(() => {
    const el = this.eventTarget.nativeElement as HTMLElement;
    el.addEventListener('click', e => {
    this.showButton = true;
    this.cd.detectChanges();
    })
    })
  • 现在按钮出现,感谢*ngIf="showButton"最初没有呈现,它在模板中声明了一个点击事件处理程序。这个处理程序再次改变了组件的属性,这次是 showMessagetrue .
    <button *ngIf="showButton" (click)="onButtonClick()">Click me!</button>

    onButtonClick() {
    this.showMessage = true;
    }
  • 当我单击它时,处理程序显然会运行并更改组件的 showMessagetrue , 但它 不触发变更检测 并且没有出现下面的消息。
    要使示例正常工作,只需从一开始就将 showButton 设置为 true,然后上面的场景就可以正常工作。

  • 问题是:这怎么可能?自从我宣布 (click)模板中的事件处理程序,它不应该在调用时总是触发更改检测吗?

    最佳答案

    我创建了 an issue在 Angular 的仓库中,事实证明,这个 行为是合乎逻辑的 ,虽然可能出乎意料。重新表述 Angular 团队在那里写的内容:

    导致 (click) 元素的代码如问题中所述,要渲染的处理程序在 Angular 区域之外运行。现在,虽然我执行了 detectChanges()手动在那里,这并不意味着代码突然神奇地在 Angular 区域中运行。它可以正常运行更改检测,但它“ 停留在 ”在不同的区域中。结果,当元素即将被渲染时,在中创建了元素的点击回调。绑定(bind)到非 Angular 区域 .这反过来意味着当它被用户点击触发时,它仍然被调用,但是不触发变更检测 .

    解决方案是在 zone.run(() => {...}) 中包装代码,该代码在 Angular 区域之外运行,但需要在组件中执行一些更改.

    所以在我的 stackblitz 复制中,在 Angular 区域之外运行的代码如下所示:

        this.zone.runOutsideAngular(() => {
    const el = this.eventTarget.nativeElement as HTMLElement;
    el.addEventListener('click', e => {
    this.zone.run(() => this.showButton = true);
    })
    })

    这与调用 detectChanges() 不同。 , 使 this.showButton = true在正确的区域中运行,因此由于使用事件处理程序运行该代码而创建的元素也被绑定(bind)到 Angular 区域。这样,事件处理程序总是 触发变化检测 在对 DOM 事件使用react时。

    这一切都归结为以下要点:在模板中声明事件处理程序 不会自动保证在所有情况下都能检测到更改 .

    关于javascript - Angular 单击事件处理程序未触发更改检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61712865/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com