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;
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的更多相关文章
- CSS3 GRID LAYOUT
CSS3 GRID LAYOUT http://www.w3cplus.com/blog/tags/356.html 中国首个开源 HTML5 跨屏前端框架 http://amazeui.org/
- 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 ...
- Unity3D 使用 UI 的 Grid Layout Group 组件。
1.首先创建一个容器,用于存放列表项的内容. 这里使用 Panel 来做为容器. 这里要注意! “Grid Layout Group”是要增加在容器的游戏对象里. 同时,只有容器对象的子对象才有排列效 ...
- WPF笔记(2.4 Grid)——Layout
原文:WPF笔记(2.4 Grid)--Layout 第一章已经简单介绍过这个容器,这一节详细介绍.Grid一般是用表格(Grid.Row 和Grid.Column )的,比StackPanel更细致 ...
- flexbox与grid layout的区别
flexbox是一种针对一维的局部布局,以轴为核心的弹性布局. grid layout是二维的更加全面的网格布局,
- CSS: Grid Layout Module
Grid Layout The CSS Grid Layout Module offers a grid-based layout system, with rows and columns, mak ...
- [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 ...
- [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 ...
- [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.
- [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 ...
随机推荐
- 【MySQL】索引和锁
前言 本文摘自数据库两大神器[索引和锁] 声明:如果没有说明具体的数据库和存储引擎,默认指的是MySQL中的InnoDB存储引擎 索引 在之前,我对索引有以下的认知: 索引可以加快数据库的检索速度 表 ...
- Redis主从配置与数据备份还原
一.主从配置: 1.下载: wget http://download.redis.io/releases/redis-4.0.9.tar.gz tar xzf redis-4.0.9.tar.gz c ...
- 自定义ngCloak
场景: 一个非常复杂的表单页面,页面有5个标签,第五个标签中又有5个标签,也就是说一共有9个标签,每个标签中都有一个表单,表单之间相互关联.所有表单项(包括复合的),有80多个数据.全部东西写在一个h ...
- 条款27:尽量少做转型动作(Minimize casting)
NOTE : 1.如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts. 如果有个设计需要转型动作,试着发展无需转型的替代设计. 2.如果转型是必须要的,试着将它隐藏于某个函 ...
- POJ 4118 开餐馆
Description 北大信息学院的同学小明毕业之后打算创业开餐馆.现在共有n 个地点可供选择.小明打算从中选择合适的位置开设一些餐馆.这 n 个地点排列在同一条直线上.我们用一个整数序列m1, m ...
- 【BZOJ 3289】 Mato的文件管理(离线算法莫队)
Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能 ...
- POJ 1144 Network (求割点)
题意: 给定一幅无向图, 求出图的割点. 割点模板:http://www.cnblogs.com/Jadon97/p/8328750.html 分析: 输入有点麻烦, 用stringsteam 会比较 ...
- sql中getdate()&convert的使用
1,sql中getdate()函数的使用: getdate()函数从SQL Server中返回当前的时间和日期,如: insert into T3(ID,AddTime) values(,GETDAT ...
- python019 Python3 File(文件) 方法
file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数: 序号 方法及描述 1 file.close() 关闭文件.关闭后文件不能再进行读写操作. 2 file.flush() ...
- 【MVC 2】MVC+EF框架结构实例:注册ID号验证
导读:本篇博客,将通过一个实例,详细介绍MVC+EF的应用.原理性的东西或者说是进一步的解耦和,请看博客: [框架结构 3]MVC+EF实体框架-原理解析.在这里,仅用MVC框架和一个EF生成的Mod ...