• 使用react-sizeme解决react-grid-layout中侧栏(抽屉)展开或隐藏时不会自适应容器大小的问题


    使用react-sizeme解决react-grid-layout中侧栏(抽屉)展开或隐藏时不会自适应容器大小的问题

    前提概要

    在上一篇博文中,我们讲到了使用react-grid-layoutecharts-for-react实现一个自定义的dashboar页面
    《使用react-grid-layout和echarts-for-react实现一个支持拖拽的自定义响应式dashboard页面》

    问题代码

    import React, {useState} from "react";
    import 'react-grid-layout/css/styles.css'
    import 'react-resizable/css/styles.css'
    import {Button} from "antd";
    import {findIndex, uniqueId} from "lodash";
    import './dashboard.css'
    import WidgetLoadingSpin from "@/pages/Dashboard/Detail/WidgetLoadingSpin";
    import {CloseOutlined, LockOutlined, QuestionCircleOutlined, UnlockOutlined} from "@ant-design/icons";
    import RGL, {Layout, WidthProvider} from "react-grid-layout";
    import {cloneDeep} from "lodash-es";
    const BarChartWidgetLazy = React.lazy(() => import('@/pages/Dashboard/Detail/Widget/BarChartWidget'));
    const PieChartWidgetLazy = React.lazy(() => import('@/pages/Dashboard/Detail/Widget/PieChartWidget'));
    const ReactGridLayout = WidthProvider(RGL);
    interface DashboardWidgetInfo {
      widgetName: string,
      layout: Layout
    }
    function DashboardGird() {
      const [widgets, setWidgets] = useState<DashboardWidgetInfo[]>([]);
      const getLayouts: any = () => {
        return cloneDeep(widgets.map(item => item.layout));
      }
      const setLayoutStatic = (widget: DashboardWidgetInfo, staticFlag: boolean) => {
        const index = findIndex(widgets, (w: any) => w.widgetName === widget.widgetName);
        if (index !== -1) {
          const updateWidget = widgets[index];
          updateWidget.layout.static = staticFlag;
          widgets.splice(index, 1, {...updateWidget});
          const newWidgets = [...widgets];
          setWidgets(newWidgets);
        }
      }
      const lockWidget = (widget: DashboardWidgetInfo) => {
        setLayoutStatic(widget, true);
      }
      const unlockWidget = (widget: DashboardWidgetInfo) => {
        setLayoutStatic(widget, false);
      }
      const onRemoveWidget = (widget: DashboardWidgetInfo) => {
        const widgetIndex = findIndex(widgets, (w: any) => w.layout.i === widget.layout.i);
        if (widgetIndex !== -1) {
          widgets.splice(widgetIndex, 1);
          const newWidgets = [...widgets];
          setWidgets(newWidgets);
        }
      }
      const getWidgetComponent = (widgetName: string) => {
        if (widgetName === 'PieChartWidget') { //可以改成策略
          return (<React.Suspense fallback={<WidgetLoadingSpin/>}>
            <PieChartWidgetLazy/>
          </React.Suspense>);
        } else {
          return (<React.Suspense fallback={<WidgetLoadingSpin/>}>
            <BarChartWidgetLazy/>
          </React.Suspense>);
        }
      }
      const createWidget = (widget: DashboardWidgetInfo) => {
        return (
          <div className={'dashboard-widget-wrapper'} key={widget.layout.i} data-grid={widget.layout}>
              <span className='dashboard-widget-header'>
                <QuestionCircleOutlined className={'dashboard-widget-header-icon'}/>
                {widget.layout.static ? <LockOutlined className={'dashboard-widget-header-icon'} onClick={() => unlockWidget(widget)}/> : (
                  <UnlockOutlined className={'dashboard-widget-header-icon'} onClick={() => lockWidget(widget)}/>)}
                <CloseOutlined className={'dashboard-widget-header-icon'} onClick={() => onRemoveWidget(widget)}/>
              </span>
            {getWidgetComponent(widget.widgetName)}
          </div>
        );
      }
      const onAddWidget = () => {
        const x = (widgets.length * 3) % 12;
        const widgetName = x % 2 == 0 ? 'BarChartWidget' : 'PieChartWidget'
        const newWidgets = [...widgets, {
          widgetName: widgetName,
          layout: {i: uniqueId(widgetName), x: x, y: Infinity, w: 3, h: 2, static: false}
        }] as DashboardWidgetInfo[];
        setWidgets(newWidgets);
      }
      const onLayoutChange = (layouts: any[]) => {
        for (const layout of layouts) {
          const updateIndex = findIndex(widgets, (w) => w.layout.i === layout.i);
          if (updateIndex !== -1) {
            const updateWidget = widgets[updateIndex];
            updateWidget.layout = {
              ...layout,
            };
            widgets.splice(updateIndex, 1, {...updateWidget});
          }
        }
        const newWidgets = [...widgets];
        setWidgets(newWidgets);
      }
      return (
        <>
          <Button onClick={onAddWidget}>add widget</Button>
          <ReactGridLayout
            cols={12}
            rowHeight={100}
            autoSize={true}
            isDraggable={true}
            isResizable={true}
            isBounded={true}
            layout={getLayouts()}
            className={'layouts'}
            onLayoutChange={onLayoutChange}>
            {widgets?.map(item => createWidget(item))}
          </ReactGridLayout>
        </>
      );
    }
    export default DashboardGird
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113

    最终效果可以看到,当我们侧栏(抽屉)移动时并不会自动帮我们调整react-grid-layout中元素的占位,也就是在最右边我们可以看到,当侧栏(抽屉)隐藏的时候,最右边是有空白的,并不会自适应填充。

    请添加图片描述

    那其实在官网中给出了解决方案:https://github.com/react-grid-layout/react-grid-layout

    Have a more complicated layout? WidthProvider is very simple and only listens to window ‘resize’ events. If you need more power and flexibility, try the SizeMe React HOC as an alternative to WidthProvider.

    react-grid-layout中提供的WidthProvider只是很简单的监听了浏览器窗口’resize’的事件,根本没办法监听到当前容器大小更变的事件,所以我们需要react-sizeme来帮助我们知道当前容器的大小

    所以我们需要首先npm install react-sizeme,然后我们就可以使用了。这里就不过多介绍如何使用,直接给出解决的代码

    解决代码

    import React, {useState} from "react";
    import 'react-grid-layout/css/styles.css'
    import 'react-resizable/css/styles.css'
    import {Button} from "antd";
    import {findIndex, uniqueId} from "lodash";
    import './dashboard.css'
    import WidgetLoadingSpin from "@/pages/Dashboard/Detail/WidgetLoadingSpin";
    import {CloseOutlined, LockOutlined, QuestionCircleOutlined, UnlockOutlined} from "@ant-design/icons";
    import ReactGridLayout from "react-grid-layout";
    import {cloneDeep} from "lodash-es";
    import {withSize} from 'react-sizeme';
    const BarChartWidgetLazy = React.lazy(() => import('@/pages/Dashboard/Detail/Widget/BarChartWidget'));
    const PieChartWidgetLazy = React.lazy(() => import('@/pages/Dashboard/Detail/Widget/PieChartWidget'));
    interface DashboardWidgetInfo {
      widgetName: string,
      layout: ReactGridLayout.Layout
    }
    function DashboardGird({ size: { width } }: any) {
      const [widgets, setWidgets] = useState<DashboardWidgetInfo[]>([]);
      const getLayouts: any = () => {
        return cloneDeep(widgets.map(item => item.layout));
      }
      const setLayoutStatic = (widget: DashboardWidgetInfo, staticFlag: boolean) => {
        const index = findIndex(widgets, (w: any) => w.widgetName === widget.widgetName);
        if (index !== -1) {
          const updateWidget = widgets[index];
          updateWidget.layout.static = staticFlag;
          widgets.splice(index, 1, {...updateWidget});
          const newWidgets = [...widgets];
          setWidgets(newWidgets);
        }
      }
      const lockWidget = (widget: DashboardWidgetInfo) => {
        setLayoutStatic(widget, true);
      }
      const unlockWidget = (widget: DashboardWidgetInfo) => {
        setLayoutStatic(widget, false);
      }
      const onRemoveWidget = (widget: DashboardWidgetInfo) => {
        const widgetIndex = findIndex(widgets, (w: any) => w.layout.i === widget.layout.i);
        if (widgetIndex !== -1) {
          widgets.splice(widgetIndex, 1);
          const newWidgets = [...widgets];
          setWidgets(newWidgets);
        }
      }
      const getWidgetComponent = (widgetName: string) => {
        if (widgetName === 'PieChartWidget') { //可以改成策略
          return (<React.Suspense fallback={<WidgetLoadingSpin/>}>
            <PieChartWidgetLazy/>
          </React.Suspense>);
        } else {
          return (<React.Suspense fallback={<WidgetLoadingSpin/>}>
            <BarChartWidgetLazy/>
          </React.Suspense>);
        }
      }
      const createWidget = (widget: DashboardWidgetInfo) => {
        return (
          <div className={'dashboard-widget-wrapper'} key={widget.layout.i} data-grid={widget.layout}>
              <span className='dashboard-widget-header'>
                <QuestionCircleOutlined className={'dashboard-widget-header-icon'}/>
                {widget.layout.static ? <LockOutlined className={'dashboard-widget-header-icon'} onClick={() => unlockWidget(widget)}/> : (
                  <UnlockOutlined className={'dashboard-widget-header-icon'} onClick={() => lockWidget(widget)}/>)}
                <CloseOutlined className={'dashboard-widget-header-icon'} onClick={() => onRemoveWidget(widget)}/>
              </span>
            {getWidgetComponent(widget.widgetName)}
          </div>
        );
      }
      const onAddWidget = () => {
        const x = (widgets.length * 3) % 12;
        const widgetName = x % 2 == 0 ? 'BarChartWidget' : 'PieChartWidget'
        const newWidgets = [...widgets, {
          widgetName: widgetName,
          layout: {i: uniqueId(widgetName), x: x, y: Infinity, w: 3, h: 2, static: false}
        }] as DashboardWidgetInfo[];
        setWidgets(newWidgets);
      }
      const onLayoutChange = (layouts: any[]) => {
        for (const layout of layouts) {
          const updateIndex = findIndex(widgets, (w) => w.layout.i === layout.i);
          if (updateIndex !== -1) {
            const updateWidget = widgets[updateIndex];
            updateWidget.layout = {
              ...layout,
            };
            widgets.splice(updateIndex, 1, {...updateWidget});
          }
        }
        const newWidgets = [...widgets];
        setWidgets(newWidgets);
      }
      return (
        <div>
          <Button onClick={onAddWidget}>add widget</Button>
          <ReactGridLayout
            cols={12}
            rowHeight={100}
            width={width}
            autoSize={true}
            isDraggable={true}
            isResizable={true}
            isBounded={true}
            layout={getLayouts()}
            className={'layouts'}
            onLayoutChange={onLayoutChange}>
            {widgets?.map(item => createWidget(item))}
          </ReactGridLayout>
        </div>
      );
    }
    export default withSize({ refreshMode: 'debounce', refreshRate: 60 })(DashboardGird);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113

    接下来我们来看看效果

    请添加图片描述

    这样我们就通过react-sizeme解决react-grid-layout中侧栏(抽屉)移动时不会调整大小的问题了

    参考

    react-sizeme: 让你的React Components知道它们的宽度和高度!

    Tired of Boring Static Dashboards? Let’s Build a Fully Customizable Dashboard in React

  • 相关阅读:
    vscode 创建代码模版
    计算机毕业设计Java教评系统(源码+系统+mysql数据库+lw文档)
    操作系统实验(5)—— 页面淘汰算法模拟实现与比较
    网工内推 | 上市公司运维专员,NA/NP认证优先,享有股票期权
    spark-submit 高频可选参数及作用
    Failed to start MySQL Community Server in Ubuntu
    这个软件可无限制免费领取金币,领取后即可自由实现AI文生图,AI Chat及其AI文生PPT等AI功能
    2022“杭电杯” 中国大学生算法设计超级联赛(5)6 7 题解
    【Docker】Docker的工具实践及root概念,时间戳的概念和Docker容器安全性设置的详细讲解
    Nginx+Tomcat负载均衡、动静分离
  • 原文地址:https://blog.csdn.net/cckevincyh/article/details/128105212