zoukankan      html  css  js  c++  java
  • react-grid-layout

    一个好用的拖拽、自适应布局 react 插件

    基本使用:

    // 显示全部 chart 内容区域
    import React,{PureComponent} from 'react';
    import {Responsive, WidthProvider } from "react-grid-layout";
    
    const ReactGridLayout = WidthProvider(Responsive);
    export default class ChartDashboard extends PureComponent {
        // 设置默认的 props
        static defaultProps = {
            className: "layout",
            rowHeight: 100,
            isDraggable: true,
            isResizable: true,
            onLayoutChange: function() {},
            cols: 12, //布局中的列数
            mounted: false
        };
        constructor(props) {
            super(props);
            this.state = {
                newCounter: 0,
                content: [],
            }
        }
        componentDidMount () {
            this.setState({
                mounted: true
            })
        }
        componentWillReceiveProps(props) {
            // ...
        }
        // 使用从此返回的 cols 来计算添加的新项目的位置
        onBreakpointChange = (breakpoint, cols) => {
            // ...
        }
        // 删除项目
        onRemoveItem = (i) => {
            // ...
        }
        // 改变某一个项目
        onLayoutChange = (layout) => {
            let layoutObj = {};
            layout.forEach(({i, x, y, w, h})=>{
                layoutObj[i] = {i, x, y, w, h}
            })
            // ...
        }
        // 改变 div 大小
        onResizeStop(a,b,) {
            // ...
        }
        render() {
            return <ReactGridLayout measureBeforeMount={this.state.mounted} useCSSTransforms={this.state.mounted} draggableCancel='禁止拖拽的元素的类名' margin={[8,8]} draggableHandle='.drag-element' ref='ReactGridLayoutRef' onResizeStop={this.onResizeStop} onLayoutChange={this.onLayoutChange} onBreakpointChange={this.onBreakpointChange}>
                    {this.state.content}
                </ReactGridLayout>
        } 
    }
    

     

    如何设置 change 时的背影:

    .react-grid-layout {
        position: relative;
        transition: height 200ms ease;
    }
    .react-grid-item {
        transition: all 200ms ease;
        transition-property: left, top;
    }
    .react-grid-item.cssTransforms {
        transition-property: transform;
    }
    .react-grid-item.resizing {
        z-index: 1;
    }
    
    .react-grid-item.react-draggable-dragging {
        transition: none;
        z-index: 3;
    }
    
    .react-grid-item.react-grid-placeholder {
        background: #000;
        opacity: 0.1;
        transition-duration: 100ms;
        z-index: 2;
        border-radius: 4px;
        -webkit-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        -o-user-select: none;
        user-select: none;
    }
    
    .react-grid-item:hover > .react-resizable-handle {
        position: absolute;
         20px;
        height: 20px;
        bottom: 0;
        right: 0;
        background: url(图片);
        background-position: bottom right;
        padding: 0 3px 3px 0;
        background-repeat: no-repeat;
        background-origin: content-box;
        box-sizing: border-box;
        cursor: se-resize;
    }
    

    我的某个项目源码:

    // 显示全部 chart 内容区域
    import React,{PureComponent} from 'react';
    import echarts from 'echarts/lib/echarts'; //必须
    import { connect } from 'react-redux';
    import {Responsive, WidthProvider } from "react-grid-layout";
    import ChartContent from './chartContent';
    import configureStore from '@/store/configureStore';
    import {getDashboardChartInfo} from '@/actions';
    import Request from '../request';
    import Editor from './quill';
    import deletePng from '@/common/images/delete.png';
    import {Tooltip} from 'antd';
    
    const ReactGridLayout = WidthProvider(Responsive);
    class ChartDashboard extends PureComponent {
        // 设置默认的 props
        static defaultProps = {
            className: "layout",
            rowHeight: 100,
            isDraggable: true,
            isResizable: true,
            onLayoutChange: function() {},
            cols: 12, //布局中的列数
            mounted: false
        };
        constructor(props) {
            super(props);
            this.state = {
                newCounter: 0,
                content: [],
            }
            this.cacheContent = [];
            this.onLayoutChange = this.onLayoutChange.bind(this);
            this.onResizeStop = this.onResizeStop.bind(this);
            this.getContent = this.getContent.bind(this);
            this.onBreakpointChange = this.onBreakpointChange.bind(this);
        }
        componentDidMount () {
            this.setState({
                mounted: true
            })
        }
        componentWillReceiveProps(props) {
            let {dashboardChartInfo} = props;
            let content = dashboardChartInfo && dashboardChartInfo.length > 0 ? this.getContent(dashboardChartInfo) : []
            this.setState ({
                dashboardChartInfo:dashboardChartInfo,
                content: content
            })
        }
        // 使用从此返回的 cols 来计算添加的新项目的位置
        onBreakpointChange(breakpoint, cols) {
            console.log(breakpoint,cols)
        }
        // 删除项目
        onRemoveItem(i) {
            let curContent = [...this.state.content];
            let stateChartInfo = [...this.state.dashboardChartInfo];
            curContent.deleteObjectInArray('key',i);
            stateChartInfo.deleteObjectInArray('position','i',i)
            this.updateDashboardInfo(stateChartInfo);
            return false;
        }
        // 改变某一个项目
        onLayoutChange(layout) {
            let layoutObj = {};
            layout.forEach(({i, x, y, w, h})=>{
                layoutObj[i] = {i, x, y, w, h}
            })
            // state 中保存的 dashboardChartInfo 信息
            let stateChartInfo = this.state.dashboardChartInfo;
            let dashboardChartInfo = stateChartInfo.map(val=>{
                let position = layoutObj[val.position.i];
                return {id:val.id,position,type:val.type||'chart'}
            });
            if (this.isContIdentical(stateChartInfo, dashboardChartInfo)) {
                this.updateDashboardInfo(dashboardChartInfo);
            }
        }
        // 改变 div 大小,重新渲染 echarts 图表
        onResizeStop(a,b,) {
            let idname = `.react-grid-layout div[data-id="${b.i}"]`;
            let parentDom = document.querySelector(idname);
            
            // let parentDom = event.target.parentElement;
            let echartDom = parentDom.querySelector('div[_echarts_instance_]');
            if(echartDom) {
                let echartObj = echarts.getInstanceByDom(echartDom);
                echartObj.resize();
            }
        }
        getContent(dashboardChartInfo) {
            return dashboardChartInfo.map((val,index)=>{
                if(val.position.y === null) {
                    val.position.y = Infinity;
                }
                if(val.type=='text') {
                    return (<div className="drag-element" key={val.position.i} data-id={val.position.i} data-grid={{...val.position}}>
                        <Editor placeholder='请输入内容...' id={val.id} dashboardChartInfo={dashboardChartInfo} user_chart_set_id={this.props.dashboardInfo && this.props.dashboardInfo.userChartSetId} curContent={val.content}/>
                        <Tooltip placement="top" title='删除'><img src={deletePng} className="remove" key={val.position.i}  onClick={this.onRemoveItem.bind(this,val.position.i)}/></Tooltip>
                    </div>)
                }else {
                    return (<div className="drag-element" key={val.position.i} data-id={val.position.i} data-grid={{...val.position}}>
                        <ChartContent id={val.id} history={this.props.history}/>
                        <Tooltip placement="top" title='删除'><img src={deletePng} className="remove" key={val.position.i}  onClick={this.onRemoveItem.bind(this,val.position.i)}/></Tooltip>
                    </div>)
                }
            })
        }    
        isContIdentical(cacheContent, content) {
            if (cacheContent.length === content.length) {
                for (let i = cacheContent.length - 1; i >= 0; i --) {
                    let cacheData = cacheContent[i].position;
                    let contData = content[i].position;
                    let flag = cacheData.i === contData.i &&
                    cacheData.x === contData.x &&
                    cacheData.y === contData.y &&
                    cacheData.w === contData.w &&
                    cacheData.h === contData.h;
                    if (!flag) return true;
                }
                return false;
            }
            return true;
        }
        /**
         * 更新 dashboard 信息
         * @param {} user_chart_set_info 
         */
        updateDashboardInfo(user_chart_set_info) {
            Request.selectDashboardInfo({
                operationType: 'edit',
                user_chart_set_id: this.props.dashboardInfo.userChartSetId,
                user_chart_set_info: JSON.stringify(user_chart_set_info)
            },(data)=>{
                if(data.code == 1) {
                    this.setState ({
                        dashboardChartInfo:user_chart_set_info,
                    })
                    configureStore.dispatch(getDashboardChartInfo(user_chart_set_info));
                }
            })
        }
        render() {
            return <div className='right-dashboard' style={{
                    paddingRight: '30px',
                    overflow: 'auto',
                    marginBottom: '20px'
                }}>
                <ReactGridLayout style={{paddingLeft: '8px'}} measureBeforeMount={this.state.mounted} useCSSTransforms={this.state.mounted} draggableCancel='.map,.quill,.remove,.edit-chart' margin={[8,8]} draggableHandle='.drag-element' ref='ReactGridLayoutRef' onResizeStop={this.onResizeStop} onLayoutChange={this.onLayoutChange} onBreakpointChange={this.onBreakpointChange}>
                    {this.state.content}
                </ReactGridLayout>
            </div>
        } 
    }
    const mapStateToProps = (state) => {
        return {
            dashboardChartInfo: state.DashBoard.dashboardChartInfo,
            dashboardInfo: state.DashBoard.dashboardInfo
        }
    }
    export default connect(mapStateToProps)(ChartDashboard);
    /**
     * 删除数组中的某个对象
     * @param {*} key1 
     * @param {*} key2 
     * @param {*} key3 
     */
    Array.prototype.deleteObjectInArray = function (key1,key2,key3) {
        if(arguments.length == 3) {
            this.forEach((val,index)=>{
                if(val[key1][key2] == key3) {
                    this.splice(index,1)
                }
            });
        }else {
            this.forEach((val,index)=>{
                if(val[key1] == key2) {
                    this.splice(index,1)
                }
            });
        }
        
        return this;
    }
    

      

  • 相关阅读:
    JSON.parse()和JSON.stringify()
    php结合layui实现前台加后台操作
    微信拨打电话功能
    视觉差效果
    前端开发面试题
    字符串分割--java中String.split()用法
    vue.js实现购物车功能
    localStorage使用总结
    canvas 实现赛车小游戏
    canvas 实现飞碟射击游戏
  • 原文地址:https://www.cnblogs.com/z-one/p/9485817.html
Copyright © 2011-2022 走看看