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 ...
随机推荐
- 学习PyQuery库
学习PyQuery库 好了,又是学习的时光啦,今天学习pyquery 来进行网页解析 常规导入模块(PyQuery库中的pyquery类) from pyquery import PyQuery as ...
- 2019年,Python工程师必考的6个面试题,Python面试题No5
第1题:Python里面如何实现tuple和list的转换? 函数tuple(seq)可以把所有可迭代的(iterable)序列转换成一个tuple, 元素不变,排序也不变 list转为tuple: ...
- 06 PhantomJS浏览器
PhantomtomJS PhantomJS是一款无界面浏览器,其自动化操作流程和谷歌浏览器是一致的.由于是无界面的,为了能够展示自动化操作流程,PhantomJS为用户提供了一个截屏的功能,使用sa ...
- 【笔记】mysql入门语句8条
1.连接到数据库服务器 mysql -h host -uroot -pXXXX 2.查看所有库 show databases; 3.选库 use 库名 4.查看库下面的表 show tables; 5 ...
- 儿子写日记 : " 夜深了,妈妈在打麻将,爸爸在上网……"
儿子写日记 : " 夜深了,妈妈在打麻将,爸爸在上网……" 爸爸检查时,很不满意地说 : " 日记源于生活,但要高于生活 !" ...
- metadata的使用以及简单的orm模式
使用sqllite3和metadata简单的封装了个简单的orm #!/usr/bim/python #-*-coding: utf-8 -*- import threading import sql ...
- PHPTaint-检测xss/sqli/shell注入的php扩展模块[转]
web渗透者习惯采用黑盒或灰盒的方面来检测一款web应用是否存在漏洞,这种检测方法可以屏蔽不少漏洞,特别是程序逻辑中的漏洞.但如果能配合白盒的源码审计(也可以叫漏洞挖掘),效果将会更好,当然人力成本也 ...
- $config['base_url'] BASE_URL
/*|------------------------------------------------| Base Site URL|--------------------------------- ...
- Nuget,程序员的功能包
导读:随着信息技术的发展,资源的共享已经成为一种文化.对于程序设计来说,我们在编写软件的时候,总有那么一些公共使用的东西,或者说需啊哟使用到别人可能已经做得很好的东西.这个时候,再去重写,并不是一个明 ...
- php-fpm.conf
[global]pid = /usr/local/php/var/run/php-fpm.piderror_log = /usr/local/php/var/log/php-fpm.loglog_le ...