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 ...
随机推荐
- laravel 数据导出
支持:php 7.0 以上 三种方案总结介绍: 第一种:最简单且不会有长久隐患.但不适合数据量多 第二种: 适合中等数据量,不会有长久隐患.但导出时极占内存 第三种:适合大量数据,不会占据 ...
- C#对象初始化的探讨
最近在弄MQ的性能监测数据埋点,无疑中用到一个Nstatsd的客户端,看到里面写过里面一种嵌套类的写法.代码如下: 客户端Client是一个密封的类,并且构造函数私有访问.然后又用一个嵌套类Curre ...
- .NET Core 文件的上传与下载
1.前言 文件导入导出是简单且常用的功能,以下示例实现了文件上传与下载的几种方法,如有不妥的地方,欢迎指正.小白一枚,在往目标前进. 2.1.文件上传 -- 纯文件 <form ac ...
- mysql汉字转拼音函数
-- 创建汉字拼音对照临时表 CREATE TABLE IF NOT EXISTS `t_base_pinyin` ( `pin_yin_` ) CHARACTER SET gbk NOT NULL, ...
- XV6环境搭建及注意事项
Ubuntu16.04SLT 64位 工具链 sudo apt-get install gcc-multilib libsdl1.2-dev, libtool-bin, libglib2.0-dev, ...
- P1979 [NOIP]华容道
[问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 B 玩的华 ...
- Atlantis(hdu1542)
题意:求n个矩阵的面积并. /* 线段树维护扫描线 把每个矩形看成两条线段,从左到右添加线段,如果是矩形左边的线段,那就给线段所在的区间(y值)cover+1,反之则cover-1. 并且如果这条线段 ...
- RQNOJ273 马棚问题
题目描述 每天,小明和他的马外出,然后他们一边跑一边玩耍.当他们结束的时候,必须带所有的马返回马棚,小明有K个马棚.他把他的马排成一排然后跟随它走向马棚,因为他们非常疲劳,小明不想让他的马做过多的移动 ...
- Codeforces936B. Sleepy Game
还好这场没打 MD什么破题 n<=100000,m<=200000的图问从s点出发能否走奇数条边到一个没有出度的点. 直观的想法:做一个bfs,$f(i,0/1)$表示从$s$出发到$i$ ...
- BZOJ——T 1707: [Usaco2007 Nov]tanning分配防晒霜
http://www.lydsy.com/JudgeOnline/problem.php?id=1707 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 8 ...