問題
最近在使用react-grid-layout 做可拖動布局霎褐,偶然發(fā)現(xiàn)陋葡,當(dāng)我登陸完之后右莱,跳到首頁會發(fā)生寬度超出,本來設(shè)定好的都是一屏的氏堤;cb086782bc5b38ba1aab3ed30f2d4ed.png
出現(xiàn)了滾動條沙绝;
原因
經(jīng)排查因為我用了內(nèi)置的響應(yīng)式 WidthProvider;他添加了一個監(jiān)聽頁面變化的方法 window.addEventListener("resize", this.onWindowResize);這個方法會獲取當(dāng)前dom的寬度鼠锈;
因為項目是layout包裹content闪檬,當(dāng)layout和當(dāng)前dom都重載時,layout還未render完畢時购笆,當(dāng)前dom的this.elementRef.current獲取的寬度會是整個屏幕粗悯;當(dāng)layout加載完畢,react-grid-layout會超出原本設(shè)定的100%由桌;
解決
我自己重寫了他的WidthProvider方法为黎;利用宏任務(wù) setTimeout 延遲獲取當(dāng)前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}
/>
);
}
};
}