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?
这不是 mouseenter
或 mouseleave
的问题。这是因为从 angular 渲染,看到这个 thread.
所以逻辑是,当 mouseenter
到 div
(慢时)它实际上调用了两次。可以按功能调试。
<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
。它会调用两次。
这里的步骤:
- 鼠标输入
- angular 将值更改为 true
- 最后一个鼠标触发位置
- 因为同样的div再次触发mouseenter
在你的情况下,你有问题快速鼠标移动不改变值 true
到 false
因为在 angular 完成渲染后,angular 不调用 mouseenter
再次。
要解决此问题,您应该避免使用模板 re-rendering。
播放DEMO.
在*ngFor中使用了hoverdivs
数组,这意味着angular会在每次检测到数组发生变化时渲染所有div。
当您 mouseenter
或 mouseleave
时,您更改数组,从而触发 div 的渲染。您鼠标悬停的 div 现在是 new div.
您可以简单地通过使用一些 angular 不会检测到变化的东西来避免这种情况,例如对象数组而不是布尔数组。
改变hoverdivs = [ false, false, false, false, false ]
至 hoverdivs = [ { status: false }, { status: false }, { status: false }, { status: false }, { status: false }, ]
如果替换整个对象,Angular 只会检测数组中的更改。如果您只是更改数组中对象的 属性,它不会检测到数组中的更改。
(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?
这不是 mouseenter
或 mouseleave
的问题。这是因为从 angular 渲染,看到这个 thread.
所以逻辑是,当 mouseenter
到 div
(慢时)它实际上调用了两次。可以按功能调试。
<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
。它会调用两次。
这里的步骤:
- 鼠标输入
- angular 将值更改为 true
- 最后一个鼠标触发位置
- 因为同样的div再次触发mouseenter
在你的情况下,你有问题快速鼠标移动不改变值 true
到 false
因为在 angular 完成渲染后,angular 不调用 mouseenter
再次。
要解决此问题,您应该避免使用模板 re-rendering。
播放DEMO.
在*ngFor中使用了hoverdivs
数组,这意味着angular会在每次检测到数组发生变化时渲染所有div。
当您 mouseenter
或 mouseleave
时,您更改数组,从而触发 div 的渲染。您鼠标悬停的 div 现在是 new div.
您可以简单地通过使用一些 angular 不会检测到变化的东西来避免这种情况,例如对象数组而不是布尔数组。
改变hoverdivs = [ false, false, false, false, false ]
至 hoverdivs = [ { status: false }, { status: false }, { status: false }, { status: false }, { status: false }, ]
Angular 只会检测数组中的更改。如果您只是更改数组中对象的 属性,它不会检测到数组中的更改。