一个好用的拖拽、自适应布局 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. [HIHO] 1048 铺地板

    历经千辛万苦,小Hi和小Ho终于到达了举办美食节的城市!虽然人山人海,但小Hi和小Ho仍然抑制不住兴奋之情,他们放下行李便投入到了美食节的活动当中.美食节的各个摊位上各自有着非常多的有意思的小游戏,其 ...

  2. curl 模拟post请求

    curl -H "Content-Type:application/json" -X POST --data '{"openId":"xxxxxxx& ...

  3. Python旅途——简单语法

    1. 前言 在我们对环境以及pycharm安装好之后,我们就可以开始我们的Python之旅了,那么,我们学习一门语言应该如何开始呢?就像我们学习汉语一样,从abcd这些拼音学起,而对于我们Python ...

  4. 数据结构实验6:C++实现二叉树类

    实验6 学号:     姓名:      专业:   6.1 实验目的 掌握二叉树的动态链表存储结构及表示. 掌握二叉树的三种遍历算法(递归和非递归两类). 运用二叉树三种遍历的方法求解有关问题. 6 ...

  5. C#sql语句如何使用占位符

    背景:在程序中,写sql语句时,可能要根据变量的值不同,SQL语句产生相应的变化.比如说存在变量StuName,根据变量值的不同,检索不同姓名的学生记录,这时需用到占位符的知识. 1,{0}占位符,代 ...

  6. 两个很实用很方便的函数核心及用法{(lower_bound)+(max_element))~~

    (1)            关于 lower_bound(a,a+n,x)-a的用法:                                                求x在数组a中的 ...

  7. HDU1272 迷宫通路数

    Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该 ...

  8. poj 3155 二分+最小割求实型最小割(最大密集子图)

    /* 最大密集子图子图裸题 解法:设源点s和汇点t 根据胡波涛的<最小割模型在信息学中的应用> s-每个点,权值为原边权和m, 每个点-t,权值为m+2*g-degree[i], 原来的边 ...

  9. (在线工具)JSON字符串转换成Java实体类(POJO)

    http://www.bejson.com/json2javapojo/ 付代码代码转换示例: public static FixMixedOrderResponse serialization(St ...

  10. HDU 2352 Verdis Quo

    罗马数字转化为十进制的值 题目非常的长 提取有效信息 并且介绍很多规则 但是事实上有用的信息就是如何加 什么时候减 当当前字母小于下一个字母时 减去当前字母的值 #include <iostre ...