zoukankan      html  css  js  c++  java
  • 【默默努力】react-drag-grid

    先放项目地址:https://github.com/Bilif/react-drag-grid
    项目运行效果

    感谢无私开源的程序员
    先看项目入口文件

    //index.js
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import * as serviceWorker from './serviceWorker';
    
    ReactDOM.render(<App />, document.getElementById('root'));
    
    // If you want your app to work offline and load faster, you can change
    // unregister() to register() below. Note this comes with some pitfalls.
    // Learn more about service workers: https://bit.ly/CRA-PWA
    serviceWorker.unregister();
    
    

    可以看到主要内容主要在App.js中
    接下来我们来看App.js

    //App.js
    import React from 'react';
    import './App.css';
    import DragLayout from './DragLayout';
    
    function App() {
      return (
        <DragLayout></DragLayout>
      );
    }
    
    export default App;
    

    我们可以看到App中主要引用的是DragLayout组件
    也就是核心功能点在DragLayout组件中
    在DragLayout中我们会看到引用了一些组件
    比如antd,用来布局以及样式
    react-grid-layout是一个好用的拖拽、自适应布局 react 插件
    它的使用方法为

    import { WidthProvider, Responsive } from "react-grid-layout";
    const ResponsiveReactGridLayout = WidthProvider(Responsive);
    

    在React的render方法中渲染可拖拽布局。ResponsiveReactGridLayout组件有多个属性。
    cols:定义了响应式布局划分成几列。
    rowHeight:响应式布局中组件的行高。
    onLayoutChange:当响应式布局中的组件发生拖拽或者放大缩小时触发该函数。

         <ResponsiveReactGridLayout
                className="layout"
                {...this.props}
                layouts={this.state.layouts}
                onLayoutChange={(layout, layouts) =>
                  this.onLayoutChange(layout, layouts)
                }
              >
                {this.generateDOM()}
              </ResponsiveReactGridLayout>
    

    使用echarts-for-react插件可以在React中调用echarts接口直接渲染出Echarts图表,只要传入相关的参数和数据即可。
    安装

    npm install --save echarts-for-react]
    npm install --save echarts
    

    使用

      let component = (
            <ReactEcharts
              option={option}
              notMerge={true}
              lazyUpdate={true}
              style={{ '100%',height:'100%'}}
            />
          )
    

    这边将三种图封装在了chart中

    //chart.js
    export function getBarChart() {
      const option = {
        tooltip: {
          trigger: 'axis',
          axisPointer: { // 坐标轴指示器,坐标轴触发有效
            type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
          }
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        xAxis: [{
          type: 'category',
          data: ['2014', '2015', '2016', '2017', '2018', '2019'],
          axisLine:{
            lineStyle:{
              color:'#8FA3B7',//y轴颜色
            }
          },
          axisLabel: {
            show: true,
            textStyle: {
              color: '#6D6D6D',
            }
          },
          axisTick: {show: false}
        }],
        yAxis: [{
          type: 'value',
          splitLine:{show: false},
          //max: 700,
          splitNumber: 3,
          axisTick: {show: false},
          axisLine:{
            lineStyle:{
              color:'#8FA3B7',//y轴颜色
            }
          },
          axisLabel: {
            show: true,
            textStyle: {
              color: '#6D6D6D',
            }
          },
        }],
        series: [
    
          {
            name: 'a',
            type: 'bar',
            barWidth: '40%',
            itemStyle: {
              normal: {
                color: '#FAD610'
              }
            },
            stack: '信息',
            data: [320, 132, 101, 134, 90, 30]
          },
          {
            name: 'b',
            type: 'bar',
            itemStyle: {
              normal: {
                color: '#27ECCE'
              }
            },
            stack: '信息',
            data: [220, 182, 191, 234, 290, 230]
          },
          {
            name: 'c',
            type: 'bar',
            itemStyle: {
              normal: {
                color: '#4DB3F5'
              }
            },
            stack: '信息',
            data: [150, 132, 201, 154, 90, 130]
          }
        ]
      };
      return option;
    }
    
    export function getLineChart() {
      //option
      const option = {
        color: ['#D53A35'],
        tooltip: {
          trigger: 'axis',
          //formatter: "{b} <br> 合格率: {c}%"
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          name: '',
          boundaryGap: false,
          axisLine:{
            show:false,
            lineStyle:{
              color:'#525252'
            }
          },
          axisTick:{
            show:false
          },
          axisLabel:{
            color:'#525252'
          },
          data: ['01', '02', '03', '04', '05', '06', '07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24']
        },
        yAxis: {
          type: 'value',
          name: '',
          axisLine:{
            show:false,
          },
          axisTick:{
            show:false
          },
          axisLabel:{
            color:'#525252'
          },
          splitLine:{
            lineStyle:{
              type:'dotted',
              color:'#AAA'//F3F3F3
            }
          }
        },
        series: [{
          name: 'a',
          type: 'line',
          symbol: 'circle',
          data: [100,120, 132, 101, 134, 90, 230, 210,80,20,90,210,200,100,120, 132, 101, 134, 90, 230, 210,80,20,90]
        }
        ]
      };
      return option;
    }
    
    export function getPieChart() {
      //option
      const option = {
        color: ['#3AA1FF', '#36CBCB', '#4ECB73', '#FBD338'],
        tooltip: {
          trigger: 'item',
          formatter: '{a} <br/>{b}: {c} ({d}%)'
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        series: [{
          name: '消费能力',
          type: 'pie',
          radius: ['40%', '55%'],
          center: ['50%', '55%'],
          avoidLabelOverlap: true,
          itemStyle: {
            normal: {
              borderColor: '#FFFFFF',
              borderWidth: 2
            }
          },
          label: {
            normal: {
              show: false,
            },
          },
          labelLine: {
            normal: {
              show: false
            }
          },
          data: [{
            name: 'a',
            value: '20'
          }, {
            name: 'b',
            value: '40'
          }, {
            name: 'c',
            value: '10'
          }, {
            name: 'd',
            value: '10'
          }]
        }]
      };
      return option;
    }
    

    通过generateDOM函数生成布局中的组件,首先先遍历组件数组,通过每个组件的类型判断生产柱状图组件,
    折线组件,还是饼图组件。每个组件必须定义一个全局唯一的key值。data-grid为每一个组件绑定了其属性。

      generateDOM = () => {
        return _.map(this.state.widgets, (l, i) => {
          let option;
          if (l.type === 'bar') {
            option = getBarChart();
          }else if (l.type === 'line') {
            option = getLineChart();
          }else if (l.type === 'pie') {
            option = getPieChart();
          }
          let component = (
            <ReactEcharts
              option={option}
              notMerge={true}
              lazyUpdate={true}
              style={{ '100%',height:'100%'}}
            />
          )
          return (
            <div key={l.i} data-grid={l}>
              <span className='remove' onClick={this.onRemoveItem.bind(this, i)}>x</span>
              {component}
            </div>
          );
        });
      };
    

    通过addItem函数来新增组件。
    每个组件属性如下:

    x: 组件在x轴坐标
    y: 组件在y轴坐标
    w: 组件宽度
    h: 组件高度
    i: 组件key值

    addItem(type,widgetId) {
        const addItem = {
          x: (this.state.widgets.length * 2) % (this.state.cols || 12),
          y: Infinity, // puts it at the bottom
          w: 2,
          h: 2,
          i: widgetId || new Date().getTime().toString(),
        };
        this.setState(
          {
            widgets: this.state.widgets.concat({
              ...addItem,
              type,
            }),
          },
        );
      };
    
    

    通过onRemoveItem函数来移除增组件。

    onRemoveItem(i) {
        console.log(this.state.widgets)
        this.setState({
          widgets: this.state.widgets.filter((item,index) => index !=i)
        });
    
      }
    

    DragLayout.js全部代码为

    //DragLayout
    import React, { PureComponent } from 'react';
    import { Layout,Button } from 'antd';
    import { WidthProvider, Responsive } from "react-grid-layout";
    import _ from "lodash";
    import ReactEcharts from 'echarts-for-react';
    import { getBarChart,getLineChart,getPieChart } from "./chart";
    
    const ResponsiveReactGridLayout = WidthProvider(Responsive);
    const { Header, Content} = Layout;
    
    export default class DragLayout extends PureComponent {
      static defaultProps = {
        cols: { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 },
        rowHeight: 100,
      };
    
      constructor(props) {
        super(props);
    
        this.state = {
          layouts: this.getFromLS("layouts") || {},
          widgets:[]
        }
      }
    
      getFromLS(key) {
        let ls = {};
        if (global.localStorage) {
          try {
            ls = JSON.parse(global.localStorage.getItem("rgl-8")) || {};
          } catch (e) {
            /*Ignore*/
          }
        }
        return ls[key];
      }
    
      saveToLS(key, value) {
        if (global.localStorage) {
          global.localStorage.setItem(
            "rgl-8",
            JSON.stringify({
              [key]: value
            })
          );
        }
      }
      generateDOM = () => {
        return _.map(this.state.widgets, (l, i) => {
          let option;
          if (l.type === 'bar') {
            option = getBarChart();
          }else if (l.type === 'line') {
            option = getLineChart();
          }else if (l.type === 'pie') {
            option = getPieChart();
          }
          let component = (
            <ReactEcharts
              option={option}
              notMerge={true}
              lazyUpdate={true}
              style={{ '100%',height:'100%'}}
            />
          )
          return (
            <div key={l.i} data-grid={l}>
              <span className='remove' onClick={this.onRemoveItem.bind(this, i)}>x</span>
              {component}
            </div>
          );
        });
      };
    
      addChart(type) {
        const addItem = {
          x: (this.state.widgets.length * 3) % (this.state.cols || 12),
          y: Infinity, // puts it at the bottom
          w: 3,
          h: 2,
          i: new Date().getTime().toString(),
        };
        this.setState(
          {
            widgets: this.state.widgets.concat({
              ...addItem,
              type,
            }),
          },
        );
      };
    
      onRemoveItem(i) {
        console.log(this.state.widgets)
        this.setState({
          widgets: this.state.widgets.filter((item,index) => index !=i)
        });
    
      }
    
      onLayoutChange(layout, layouts) {
        this.saveToLS("layouts", layouts);
        this.setState({ layouts });
      }
    
      render() {
       return(
         <Layout>
          <Header style={{ position: 'fixed', zIndex: 1,  '100%','padding': '0 30px' }}>
            <Button type="primary" style={{'marginRight':'7px'}} onClick={this.addChart.bind(this,'bar')}>添加柱状图</Button>
            <Button type="primary" style={{'marginRight':'7px'}} onClick={this.addChart.bind(this,'line')}>添加折线图</Button>
            <Button type="primary" style={{'marginRight':'7px'}} onClick={this.addChart.bind(this,'pie')}>添加饼图</Button>
          </Header>
          <Content style={{ marginTop: 44 }}>
            <div style={{ background: '#fff', padding: 20, minHeight: 800 }}>
              <ResponsiveReactGridLayout
                className="layout"
                {...this.props}
                layouts={this.state.layouts}
                onLayoutChange={(layout, layouts) =>
                  this.onLayoutChange(layout, layouts)
                }
              >
                {this.generateDOM()}
              </ResponsiveReactGridLayout>
            </div>
          </Content>
        </Layout>
       )}
    }
    

    部分讲解内容学习自博客:https://juejin.im/post/5cda5719e51d453a36384923

  • 相关阅读:
    Hibernate关联的集合对象排序
    Hibernate级联查询的分页问题
    Hibernate双向一对多级联保存优化
    Struts流程分析+源码分析
    jsp自定义函数库
    Java异常处理和设计
    struts2总体介绍
    struts和struts2的区别
    搭建struct环境
    struts-config.xml的配置
  • 原文地址:https://www.cnblogs.com/smart-girl/p/11428207.html
Copyright © 2011-2022 走看看