一个好用的拖拽、自适应布局 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;
width: 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;
}

  

react-grid-layout的更多相关文章

  1. CSS3 GRID LAYOUT

    CSS3 GRID LAYOUT http://www.w3cplus.com/blog/tags/356.html 中国首个开源 HTML5 跨屏前端框架 http://amazeui.org/

  2. iphone Dev 开发实例9:Create Grid Layout Using UICollectionView in iOS 6

    In this tutorial, we will build a simple app to display a collection of recipe photos in grid layout ...

  3. Unity3D 使用 UI 的 Grid Layout Group 组件。

    1.首先创建一个容器,用于存放列表项的内容. 这里使用 Panel 来做为容器. 这里要注意! “Grid Layout Group”是要增加在容器的游戏对象里. 同时,只有容器对象的子对象才有排列效 ...

  4. WPF笔记(2.4 Grid)——Layout

    原文:WPF笔记(2.4 Grid)--Layout 第一章已经简单介绍过这个容器,这一节详细介绍.Grid一般是用表格(Grid.Row 和Grid.Column )的,比StackPanel更细致 ...

  5. flexbox与grid layout的区别

    flexbox是一种针对一维的局部布局,以轴为核心的弹性布局. grid layout是二维的更加全面的网格布局,

  6. CSS: Grid Layout Module

    Grid Layout The CSS Grid Layout Module offers a grid-based layout system, with rows and columns, mak ...

  7. [Grid Layout] Use the repeat function to efficiently write grid-template values

    We can use the repeat() function if we have repeating specifications for columns and rows. With the  ...

  8. [Grid Layout] Describe a grid layout using named grid lines

    We can use named grid lines to describe our grid layout. Let’s see how to apply this to our grid-tem ...

  9. [Grid Layout] Specify a grid gutter size with grid-gap

    It’s beautifully straightforward to add a gutter to our grid layout. Let’s apply one with grid-gap.

  10. [CSS] Get up and running with CSS Grid Layout

    We’ll discuss the display values pertinent to CSS Grid Layout – grid, inline-grid, and subgrid. Then ...

随机推荐

  1. 【MySQL】索引和锁

    前言 本文摘自数据库两大神器[索引和锁] 声明:如果没有说明具体的数据库和存储引擎,默认指的是MySQL中的InnoDB存储引擎 索引 在之前,我对索引有以下的认知: 索引可以加快数据库的检索速度 表 ...

  2. Redis主从配置与数据备份还原

    一.主从配置: 1.下载: wget http://download.redis.io/releases/redis-4.0.9.tar.gz tar xzf redis-4.0.9.tar.gz c ...

  3. 自定义ngCloak

    场景: 一个非常复杂的表单页面,页面有5个标签,第五个标签中又有5个标签,也就是说一共有9个标签,每个标签中都有一个表单,表单之间相互关联.所有表单项(包括复合的),有80多个数据.全部东西写在一个h ...

  4. 条款27:尽量少做转型动作(Minimize casting)

    NOTE : 1.如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts. 如果有个设计需要转型动作,试着发展无需转型的替代设计. 2.如果转型是必须要的,试着将它隐藏于某个函 ...

  5. POJ 4118 开餐馆

    Description 北大信息学院的同学小明毕业之后打算创业开餐馆.现在共有n 个地点可供选择.小明打算从中选择合适的位置开设一些餐馆.这 n 个地点排列在同一条直线上.我们用一个整数序列m1, m ...

  6. 【BZOJ 3289】 Mato的文件管理(离线算法莫队)

    Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能 ...

  7. POJ 1144 Network (求割点)

    题意: 给定一幅无向图, 求出图的割点. 割点模板:http://www.cnblogs.com/Jadon97/p/8328750.html 分析: 输入有点麻烦, 用stringsteam 会比较 ...

  8. sql中getdate()&convert的使用

    1,sql中getdate()函数的使用: getdate()函数从SQL Server中返回当前的时间和日期,如: insert into T3(ID,AddTime) values(,GETDAT ...

  9. python019 Python3 File(文件) 方法

    file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数: 序号 方法及描述 1 file.close() 关闭文件.关闭后文件不能再进行读写操作. 2 file.flush() ...

  10. 【MVC 2】MVC+EF框架结构实例:注册ID号验证

    导读:本篇博客,将通过一个实例,详细介绍MVC+EF的应用.原理性的东西或者说是进一步的解耦和,请看博客: [框架结构 3]MVC+EF实体框架-原理解析.在这里,仅用MVC框架和一个EF生成的Mod ...