OnMouseLeave 事件仅在鼠标指针离开父元素后触发。

huangapple go评论69阅读模式
英文:

OnMouseLeave Event only firing after the mouse pointer leaves parent element

问题

我有一个包含OnMouseEnter()的div元素,它会更改其类,并且有一个OnMouseLeave(),会恢复其类,onMouseLeave()只在鼠标指针离开元素的父div后起作用。

查看工作示例

更多细节 - 基本上,我有一个父div(称为canvas),其中包含子div(cells)来表示矩阵,子div在鼠标进入时改变颜色,并在鼠标离开时恢复到原始颜色,问题是cells在鼠标进入时改变颜色,但只有在指针离开它们的父div时才恢复颜色。

 const [canvas, setcanvas] = useState([[]]);
 const handleenter1 = (row, col) => {
       const a = []
       for (var i = 0; i<50; i++){
        a.push([]);
         for (var j=0; j<20; j++){
           if (i=== row && j === col){
              var obj = {x: i, y: j,  status: "wall"};
              a[i].push(obj);
           }
           else {
               obj = canvas[i][j];
              a[i].push(obj);
           }
       
        }
     }
     setcanvas(a);  
}
const handleleave1 = (row, col ) => {}
const create =  () => {
    let a = [];
 for (var i = 0; i<50; i++){
    a.push([]);
     for (var j=0; j<20; j++){
      if (i === 10 && j === 10){
         var obj = {x: i, y: j,  status: "starter"};
        a[i].push(obj);
      }
      else {
          obj = {x: i, y: j, status: "space"};
        a[i].push(obj);
      }
        
    }
 }
 setcanvas(a);

 }
 useEffect(create, []);  
const m = canvas.map((objlist,index1)=> {
    return (objlist.map((obj,index) => {
        return (
        <div key = {`${index1} ${index}`} 
             onMouseEnter ={()=> {handleenter1(obj.x,obj.y)}}
             onMouseLeave = {()=> { handleleave1(obj.x ,obj.y) }}>
        </div>);
    }));
});
英文:

I have a div element with OnMouseEnter() that changes its class and a OnMouseLeave() that reverts its class, the onMouseLeave() only works after the mouse pointer leaves the parent div of the element.

Working example here - https://codesandbox.io/s/old-violet-7ipbvb?file=/src/Grid.jsx&resolutionWidth=320&resolutionHeight=675

More details - Basically I have a parent div (called canvas) that has child divs (cells) inside to represent a matrix, the child divs change color on mouse enter and revert to original color on mouseleave, the problem is that cells change color on mouse enter but only revert the color when the pointer leave their parent div.

 const [canvas, setcanvas] = useState([[]]);
const handleenter1 = (row, col) => {
const a = []
for (var i = 0; i<50; i++){
a.push([]);
for (var j=0; j<20; j++){
if (i=== row && j === col){
var obj = {x: i, y: j,  status: "wall"};
a[i].push(obj);
}
else {
obj = canvas[i][j];
a[i].push(obj);
}
}
}
setcanvas(a);  
}
const handleleave1 = (row, col ) => {}
const create =  () => {
let a = [];
for (var i = 0; i<50; i++){
a.push([]);
for (var j=0; j<20; j++){
if (i === 10 && j === 10){
var obj = {x: i, y: j,  status: "starter"};
a[i].push(obj);
}
else {
obj = {x: i, y: j, status: "space"};
a[i].push(obj);
}
}
}
setcanvas(a);
}
useEffect(create, []);
const m = canvas.map((objlist,index1)=> {
return (objlist.map((obj,index) => {
return (
<div key = {`${index1} ${index}`} 
onMouseEnter ={()=> {handleenter1(obj.x,obj.y)}}
onMouseLeave = {()=> { handleleave1(obj.x ,obj.y) }}>
</div>);
}));
});

答案1

得分: 1

问题出在你的handleenter1handleleave1函数之间存在竞态条件,其中mouseleave在及时看不到更新的canvas,这就是为什么它错误地保留了先前的黑色单元格。

如果你重构这些函数以命令式地更新已知行/列的画布状态,就不会遇到这个问题。现在setcanvas不会发生冲突,因为它只是设置它关心的一个单元格,而不是所有其他单元格。

这里是一个可运行的沙盒

const handleenter1 = (row, col) => {
  setcanvas((c) => {
    const p = [...c];
    p[row][col].status = "wall";
    return p;
  });
};

const handleleave1 = (row, col) => {
  setcanvas((c) => {
    const p = [...c];
    p[row][col].status = "space";
    return p;
  });
};
英文:

The issue is a race-condition between your handleentter1 and handleleave1 functions where mouseleave does not see the updated canvas in time, which is why it mistakenly keeps the previous cell black.

If you refactor the functions to imperatively update the canvas state's status for the known row/column, you won't run into this issue. Now the setcanvas does not collide since it's just setting the one cell it cares about and not all the other cells.

Here's a working sandbox:

const handleenter1 = (row, col) => {
setcanvas((c) => {
const p = [...c];
p[row][col].status = "wall";
return p;
});
};
const handleleave1 = (row, col) => {
setcanvas((c) => {
const p = [...c];
p[row][col].status = "space";
return p;
});
};

huangapple
  • 本文由 发表于 2023年2月23日 22:19:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75546066.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定