Mab*_*eek 5 javascript reactjs react-hooks
因此,我为作为图表库一部分的工具提示创建了简单的边缘检测。我无法使用已经实现边缘检测的工具提示(如 MUI 工具提示),因为图表软件只允许 HTML 工具提示,所以我只能创建一个仅对屏幕右侧进行边缘检测的 React 组件。由于工具提示始终向右侧打开,因此我只需处理右侧即可。
因此,当悬停靠近边缘时,工具提示会检查它与边缘的距离,然后我使用 CSS 偏移将工具提示放置在远离屏幕右侧的点。
该组件如下所示:
export const MyTooltip = ({ children }) => {
useEffect(() => {
const container =
document.getElementById('tooltip');
if (container) {
const x = container.getBoundingClientRect().x;
if (x > window.outerWidth - 200) {
container.style.left = 'auto';
container.style.right = '0';
container.style.transform = `translateX(${
window.outerWidth - x - 40
}px)`;
}
}
}, []);
return (
<TooltipStyle>
<div id="tooltip" className="custom-tooltip">
{children}
</div>
</TooltipStyle>
);
};
Run Code Online (Sandbox Code Playgroud)
TooltipStyle 是一个样式化组件,具有用于背景、填充等的 .custom-tooltip 类的 CSS。200px 是所有实例中工具提示的宽度,40px 是填充。
问题:有时,当工具提示在 DOM 中呈现时,页面会瞬间“闪烁”。非常难看。我知道这是因为 useEffect 挂钩中的代码实际上设置了工具提示的偏移量,但我不确定什么是好的解决方案。
任何帮助深表感谢!谢谢。
如果您可以在 Codesandbox 上提供最小的可重复性,那就太好了。例如,https://codesandbox.io/s/me6kg
在您的代码中,当用户将鼠标悬停在容器上时,您每次都会创建一个新的工具提示。它被放置在 DOM 上,然后您使用钩子更改元素上的 CSS 属性。
如果您避免重新渲染工具提示,那么它可能会解决问题。我们可以shouldComponentUpdate为此使用生命周期。
body {
padding: 2rem;
white-space: nowrap;
}
div {
display: inline-block;
}Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js" crossorigin="anonymous"></script>
<div id="root">App will go here</div>
<script type="text/babel">
const root = ReactDOM.createRoot(document.getElementById('root'));
class Tooltip extends React.Component {
constructor(props) {
super(props);
this.shown = false;
this.self = React.createRef(null);
}
componentDidMount() {
this.shown = true;
}
shouldComponentUpdate(nextProps, nextState) {
let ref = this.self.current;
let portWidth = 0;
if (document.documentElement)
portWidth = document.documentElement.clientWidth; //iframe
else
portWidth = window.outerWidth;
let left = '0px';
if (ref) {
const x = ref.getBoundingClientRect().x;
if (x > portWidth - 200 - 40) {
left = `${portWidth - x - 40 - 200}px`;
}
}
ref.style.left = left;
ref.style.visibility = nextProps.show ? 'visible' : 'hidden';
if (!this.shown) {
return true;
}
// prevent rerenders
return false;
}
render() {
console.log('Render a tooltip.');
const styles = {
position: 'absolute',
width: '200px',
color: 'white',
backgroundColor: 'black',
top: '-2rem',
left: this.props.left ? this.props.left : '0px',
visibility: this.props.show ? 'visible' : 'hidden',
};
return (
<div ref={this.self} style={styles}>
{this.props.children}
</div>
);
}
}
class Box extends React.Component {
constructor(props) {
super(props);
this.state = {show: false};
this.handleEnter = this.handleEnter.bind(this);
this.handleLeave = this.handleLeave.bind(this);
}
handleEnter() {
this.setState({ show: true });
}
handleLeave() {
this.setState({ show: false });
}
render() {
const styles = {
border: '1px solid gray',
height: '100px',
width: '300px',
position: 'relative',
left: this.props.left ? this.props.left : '0px',
};
return (
<div
style={styles}
onMouseEnter={this.handleEnter}
onMouseLeave={this.handleLeave}
>
{this.props.content}
<Tooltip show={this.state.show}>
I am<em><b>{this.props.content}</b></em>
</Tooltip>
</div>
);
}
}
root.render(
<React.Fragment>
<Box content="Box 1" />
<Box content="Box 2" left="calc(100vw - 300px)" />
</React.Fragment>
);
</script>Run Code Online (Sandbox Code Playgroud)
使用水平滚动并检查工具提示位置。
注意:如果您在输出中没有看到水平滚动条,请减小浏览器宽度。
这只是一个最低限度的代码。可以进行许多改进。
| 归档时间: |
|
| 查看次数: |
997 次 |
| 最近记录: |