【问题标题】:Need to click twice to trigger (click) event需要点击两次才能触发(点击)事件
【发布时间】:2023-03-17 06:34:01
【问题描述】:

我遇到的问题是,在特定场景下,我需要单击两次才能触发 Angular 6 组件中 DIV 上的(单击)事件。

我意识到提供一些示例代码可能会更有帮助。但是正确传达所需的代码段数量和清理的需要太多了,我担心太多无法消化,甚至可能无法证明对任何人都是可重现的。因此,我将尝试描述我正在做的事情以及到目前为止我尝试过的事情,希望有人能够为我指明正确的方向或给我一些关于寻找什么的额外想法。

我的应用程序是一个搜索引擎,它在返回和显示结果时还会显示一个方面列表,以进一步缩小结果范围。例如,构面可能包括相关类别的列表,每个类别旁边都有一个复选框。当用户选择复选框时,搜索结果会缩小,仅显示符合所选类别的结果。方面列表仅在初始搜索时构建一次,并保持不变,直到完成全新的搜索。然后,用户可以单击结果项目以导航到详细信息页面,该页面显示有关他们选择的结果项目的更详细的详细信息。

分面使用以下 HTML 模板 sn-p 显示:

<div class="facet-spacer-top"></div>
            <ng-container *ngIf="facets">
                <ng-container *ngFor="let facet of facets; let index = index">
                    <ng-container *ngIf="facet.isFacetList()">
                        <facet-list-comp [facet]="facet" [facetIndex]="index" (facetChangeEvent)='onFacetChange($event)'></facet-list-comp>
                    </ng-container>
                    <ng-container *ngIf="facet.isFacetDateRange()">
                        <facet-date-range-comp [facet]="facet" (facetChangeEvent)='onFacetChange($event)'></facet-date-range-comp>
                    </ng-container>
                </ng-container>
            </ng-container>

搜索结果以如下 HTML 模板 sn-p 显示:

 <div *ngFor="let rowNum of results | rows:3; let idx=index;" class="row result-row no-gutter">
                    <div *ngFor="let result of results | slice:(idx*3):((idx+1)*3); let jdx=index;" class="col-md-4">
                        <ng-container *ngComponentOutlet="getResultComponent(); injector: getProvider(result, (idx * 3) + jdx);"></ng-container>
                    </div>
                </div>

结果是动态添加的,因此可以使用特定结果的正确组件类型来显示结果。例如,我们的结果可能包括自行车和汽车。我们用来显示自行车结果的组件与我们用来显示汽车结果的组件不同。

有趣的是,这一切都非常有效,当没有选择任何方面值来配对结果时,单击搜索结果项将按预期打开详细信息。但是,如果用户选择一个方面(例如选择一个类别)。然后,当用户第一次点击结果时,什么也没有发生。但是,如果用户坚持并再次单击,详细信息将按预期打开。测试表明,如果用户实际单击页面上的任何位置,然后单击结果,则详细信息将按预期打开。所以这几乎就像页面需要重新获得“焦点”一样。很奇怪。

到目前为止,我已经尝试放弃 Angular (click) 事件绑定来获取句柄 DOM HTML 元素并自己附加事件。我试图在结果加载后以编程方式将焦点设置到页面上的一个元素。加载搜索结果后,我尝试以编程方式单击页面上的 DIV 元素。所有这些都导致了相同的行为。

我尝试过调试,但尝试单步调试 Angular 和 zone.js 代码是一场噩梦!!!当用户单击搜索结果时,我在代码中调用的函数上设置了断点。第一次单击时永远不会到达它。仅在第二次单击时。所以这个问题似乎发生在 Angular 或 zone.js 的某个地方。这可能是一条红鲱鱼,但是当我尝试在调试器中遍历代码时,似乎该事件在 zone.js 中丢失了。但我不确定。

我知道这并不理想并且可能过于抽象,但我没有想法。因此,如果您有任何想法,我们将不胜感激!

【问题讨论】:

  • 只是一些可能的问题。当您单击时,*ngFor 元素会被重置,因此不会注册。请参阅此answertrackBy 添加到您的*ngFor。另一个问题是处理程序以某种方式在区域外运行。使用ngZone.run() 将其恢复到区域中。检查NgZone.isInAngularZone()
  • 非常感谢您花时间阅读我的问题并提供一些可以查看的地方。我忘了提到我确实看过 NgZone.isInAngularZone() 和 ngZone.run()。我有点被他们弄糊涂了,我应该在哪里调用 ngZone.run()?我会把它放在我的组件中还是放在子 serahc 结果组件中,我想在生命周期中什么时候调用它?我会不带参数调用它吗?谢谢!
  • 这可能是 facetChangeEvent 在角度之外运行.. 或者你的点击事件是。但是在您的 html sn-p 中,我看不到单击事件处理。 ngZone.run() 应该使用处理单击事件的匿名函数调用,以及您想要执行的操作。 Google上有很多示例如何:)但我应该从ngFor开始,我的猜测是问题就在那里
  • 我试过 trackBy 看看它是否能解决我的问题,但在实施后我遇到了同样的问题。我试图只使用我显示的结果中的 id 作为 trackBy 值。然后,我尝试为生成结果的搜索附加一个日期时间戳,以查看这是否有所不同。两者都不起作用,并且都导致了必须单击两次的相同问题。顺便说一句.. 对于任何跟随的人,trackBy 函数不会绑定到组件对象,所以“this”可能不是你想的那样:-)。接下来我将阅读 Zones,看看是否能解决我的问题。谢谢!
  • 我遇到了同样的问题,trackBy 方法修复了它

标签: angular zone.js


【解决方案1】:

看来这完全是一条红鲱鱼。该问题似乎与动态添加的组件没有任何关系,而是与 facet 本身有关,它是一个复选框。

我仍然不确定问题是什么,但这个问题和线程似乎与我遇到的问题不再相关。

谢谢大家!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多