Angular *ngFor 未调用鼠标离开

Angular mouse leave not called with *ngFor

(mouseleave) 指令无效,如果它是用 *ngFor 生成的:

@Component({
  selector: 'my-app',
  template: `
  <ng-container *ngFor="let item of hoverdivs; index as i">
      <div style="background-color: grey" (mouseenter)="hoverdivs[i]=true" (mouseleave)="hoverdivs[i]=false">
      <p>Hoverable div #{{i}}</p>
      <p> hover status: {{item}} </p>
    </div>
  </ng-container>


  `,
})
export class App {
  hover:boolean;

  hoverdivs = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]

  constructor() {
  }
}

My working example can be seen here: 如果鼠标移动速度足够快,可以看到部分div"stuck"处于悬停状态

有没有办法强制调用 mouseleave?

这不是 mouseentermouseleave 的问题。这是因为从 angular 渲染,看到这个 thread.

所以逻辑是,当 mouseenterdiv(慢时)它实际上调用了两次。可以按功能调试。

<div style="background-color: grey; height: 80px; margin-bottom: 15px;"
    (mouseenter)="fire($event, i)"
    (mouseleave)="fire($event, i)">
      Hoverable div #{{i}}
      hover status: {{hoverdivss[i]}}
    </div>

fire(e,key) {
    e.stopPropagation();
    console.log(key)
  }

即使你输入 e.stopPropagation(); 它也不会起作用,因为 angular 会改变 hoverdivs 和 re-render 模板并最终再次触发 mouseenter。它会调用两次。

这里的步骤:

  1. 鼠标输入
  2. angular 将值更改为 true
  3. 最后一个鼠标触发位置
  4. 因为同样的div再次触发mouseenter

在你的情况下,你有问题快速鼠标移动不改变值 truefalse 因为在 angular 完成渲染后,angular 不调用 mouseenter 再次。

要解决此问题,您应该避免使用模板 re-rendering。

播放DEMO.

在*ngFor中使用了hoverdivs数组,这意味着angular会在每次检测到数组发生变化时渲染所有div。

当您 mouseentermouseleave 时,您更改数组,从而触发 div 的渲染。您鼠标悬停的 div 现在是 new div.

您可以简单地通过使用一些 angular 不会检测到变化的东西来避免这种情况,例如对象数组而不是布尔数组。

改变hoverdivs = [ false, false, false, false, false ]hoverdivs = [ { status: false }, { status: false }, { status: false }, { status: false }, { status: false }, ]

如果替换整个对象,

Angular 只会检测数组中的更改。如果您只是更改数组中对象的 属性,它不会检测到数组中的更改。

工作演示:http://plnkr.co/edit/nftBj9W4wKC2K5Se9xEr?p=info