问题
最近在使用react-grid-layout 做可拖动布局,偶然发现,当我登陆完之后,跳到首页会发生宽度超出,本来设定好的都是一屏的;
出现了滚动条;
原因
经排查因为我用了内置的响应式 WidthProvider;他添加了一个监听页面变化的方法 window.addEventListener("resize", this.onWindowResize);这个方法会获取当前dom的宽度;
因为项目是layout包裹content,当layout和当前dom都重载时,layout还未render完毕时,当前dom的this.elementRef.current获取的宽度会是整个屏幕;当layout加载完毕,react-grid-layout会超出原本设定的100%;
解决
我自己重写了他的WidthProvider方法;利用宏任务 setTimeout 延迟获取当前dom的宽度,以此解决 react-grid-layout 宽度超出问题!
WidthProvider 核心代码
onWindowResize = () => {
if (!this.mounted) return;
let _ = this;
let node = "";
setTimeout(() => {
node = this.elementRef.current;
if (node instanceof HTMLElement && node.offsetWidth) {
_.setState({ width: node.offsetWidth });
}
}, 0);
};
WidthProvider 全部代码
import * as React from "react";
import clsx from "clsx";
const layoutClassName = "react-grid-layout";
export default function WidthProvideRGL(ComposedComponent) {
return class WidthProvider extends React.Component {
static defaultProps = {
measureBeforeMount: false,
};
// static propTypes = {
// measureBeforeMount: PropTypes.bool,
// };
state = {
width: 1280,
};
elementRef = React.createRef();
mounted = false;
componentDidMount() {
this.mounted = true;
window.addEventListener("resize", this.onWindowResize);
// Call to properly set the breakpoint and resize the elements.
// Note that if you're doing a full-width element, this can get a little wonky if a scrollbar
// appears because of the grid. In that case, fire your own resize event, or set `overflow: scroll` on your body.
this.onWindowResize();
}
componentWillUnmount() {
window.removeEventListener("resize", this.onWindowResize);
}
onWindowResize = () => {
if (!this.mounted) return;
let _ = this;
let node = "";
setTimeout(() => {
node = this.elementRef.current;
if (node instanceof HTMLElement && node.offsetWidth) {
_.setState({ width: node.offsetWidth });
}
}, 0);
};
render() {
const { measureBeforeMount, ...rest } = this.props;
if (measureBeforeMount && !this.mounted) {
return (
<div
className={clsx(this.props.className, layoutClassName)}
style={this.props.style}
ref={this.elementRef}
/>
);
}
return (
<ComposedComponent
innerRef={this.elementRef}
{...rest}
{...this.state}
/>
);
}
};
}