React 组件在 Firefox 和 Chrome 中的行为不同
React component behaves differently in Firefox and Chrome
我编写了一个 React 组件 Tooltipable
,它能够包装另一个组件并为其显示工具提示。
它在 Firefox 中运行良好。但是,在 Chrome - 有时 - 当元素悬停在其上时,工具提示显示不一致。
有人可以解释这种行为并建议如何纠正吗?我相信它与 React 并没有真正的关系,只是我解决问题的方式 and/or 这两个浏览器呈现内容的方式。
这是一个 CodePen:
这是一个工作示例。
我做了以下事情:
- 已将
mouseover
替换为 mousemove
。
- 已将
mouseout
替换为 mouseleave
。
- 固定列表标记(
li
应该是 ul
的直接子代。您可以避免将列表与 Flexbox
或其他技术一起使用,它应该仍然有效)。
- 我刚刚在光标和工具提示之间添加了一些 space(我添加了 5px,但 1px 也应该可以解决问题)。如果您不这样做,每次出现工具提示时,
mouseleave
事件都会在文本元素上触发(产生您注意到的故障效果)。
const Tooltip = ({x, y, content, visible}) => {
const style = {
position: 'fixed',
left: x + 'px',
top: y + 'px',
background: 'black',
color: 'white',
padding: '.5%'
};
const tooltip = <span style={style}>{content}</span>;
return visible ? tooltip : null;
};
const Tooltipable = ({component, tooltipContent}) => {
const [tooltipXy, setTooltipXy] = React.useState({x: 0, y: 0});
const [tooltipVisible, setTooltipVisible] = React.useState(false);
const handleMouseOver = (e) => {
setTooltipXy({x: e.clientX + 5, y: e.clientY + 5});
setTooltipVisible(true);
};
const handleMouseOut = () => {
setTooltipVisible(false);
};
return (
<li>
<span
style={{background: 'pink'}}
onMouseLeave={handleMouseOut}
onMouseMove={handleMouseOver}>
{component}
</span>
<Tooltip
x={tooltipXy.x}
y={tooltipXy.y}
content={tooltipContent}
visible={tooltipVisible}
/>
</li>
);
};
const Todos = ({todos}) => (
<ul>
{todos.map((todo, index) => {
const component = (
<span style={{background: 'powderblue', display: 'inline'}}>
{todo.text}
</span>
);
return (
<Tooltipable
key={index}
component={component}
tooltipContent={'Created ' + todo.createdOn}
/>
);
})}
</ul>
);
const App = () => {
const todos = [
{text: 'clean car', createdOn: 'yesterday'},
{text: 'fix windows', createdOn: 'two days ago'},
{text: 'go shopping', createdOn: 'today'},
{text: 'meet family', createdOn: 'five days ago'},
{text: 'clean car', createdOn: 'yesterday'},
{text: 'fix windows', createdOn: 'two days ago'},
{text: 'go shopping', createdOn: 'today'},
{text: 'meet family', createdOn: 'five days ago'},
{text: 'clean car', createdOn: 'yesterday'},
{text: 'fix windows', createdOn: 'two days ago'},
{text: 'go shopping', createdOn: 'today'},
{text: 'meet family', createdOn: 'five days ago'},
{text: 'clean car', createdOn: 'yesterday'},
{text: 'fix windows', createdOn: 'two days ago'},
{text: 'go shopping', createdOn: 'today'},
{text: 'meet family', createdOn: 'five days ago'}
];
return <Todos todos={todos} />;
};
ReactDOM.render(<App />, document.getElementById('root'));
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
</head>
<body>
<div id="root">
</body>
</html>
我编写了一个 React 组件 Tooltipable
,它能够包装另一个组件并为其显示工具提示。
它在 Firefox 中运行良好。但是,在 Chrome - 有时 - 当元素悬停在其上时,工具提示显示不一致。
有人可以解释这种行为并建议如何纠正吗?我相信它与 React 并没有真正的关系,只是我解决问题的方式 and/or 这两个浏览器呈现内容的方式。
这是一个 CodePen:
这是一个工作示例。
我做了以下事情:
- 已将
mouseover
替换为mousemove
。 - 已将
mouseout
替换为mouseleave
。 - 固定列表标记(
li
应该是ul
的直接子代。您可以避免将列表与Flexbox
或其他技术一起使用,它应该仍然有效)。 - 我刚刚在光标和工具提示之间添加了一些 space(我添加了 5px,但 1px 也应该可以解决问题)。如果您不这样做,每次出现工具提示时,
mouseleave
事件都会在文本元素上触发(产生您注意到的故障效果)。
const Tooltip = ({x, y, content, visible}) => {
const style = {
position: 'fixed',
left: x + 'px',
top: y + 'px',
background: 'black',
color: 'white',
padding: '.5%'
};
const tooltip = <span style={style}>{content}</span>;
return visible ? tooltip : null;
};
const Tooltipable = ({component, tooltipContent}) => {
const [tooltipXy, setTooltipXy] = React.useState({x: 0, y: 0});
const [tooltipVisible, setTooltipVisible] = React.useState(false);
const handleMouseOver = (e) => {
setTooltipXy({x: e.clientX + 5, y: e.clientY + 5});
setTooltipVisible(true);
};
const handleMouseOut = () => {
setTooltipVisible(false);
};
return (
<li>
<span
style={{background: 'pink'}}
onMouseLeave={handleMouseOut}
onMouseMove={handleMouseOver}>
{component}
</span>
<Tooltip
x={tooltipXy.x}
y={tooltipXy.y}
content={tooltipContent}
visible={tooltipVisible}
/>
</li>
);
};
const Todos = ({todos}) => (
<ul>
{todos.map((todo, index) => {
const component = (
<span style={{background: 'powderblue', display: 'inline'}}>
{todo.text}
</span>
);
return (
<Tooltipable
key={index}
component={component}
tooltipContent={'Created ' + todo.createdOn}
/>
);
})}
</ul>
);
const App = () => {
const todos = [
{text: 'clean car', createdOn: 'yesterday'},
{text: 'fix windows', createdOn: 'two days ago'},
{text: 'go shopping', createdOn: 'today'},
{text: 'meet family', createdOn: 'five days ago'},
{text: 'clean car', createdOn: 'yesterday'},
{text: 'fix windows', createdOn: 'two days ago'},
{text: 'go shopping', createdOn: 'today'},
{text: 'meet family', createdOn: 'five days ago'},
{text: 'clean car', createdOn: 'yesterday'},
{text: 'fix windows', createdOn: 'two days ago'},
{text: 'go shopping', createdOn: 'today'},
{text: 'meet family', createdOn: 'five days ago'},
{text: 'clean car', createdOn: 'yesterday'},
{text: 'fix windows', createdOn: 'two days ago'},
{text: 'go shopping', createdOn: 'today'},
{text: 'meet family', createdOn: 'five days ago'}
];
return <Todos todos={todos} />;
};
ReactDOM.render(<App />, document.getElementById('root'));
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
</head>
<body>
<div id="root">
</body>
</html>