vue-grid-layout是一个非常优秀的vue栅格拖动布局的组件,使用方法请参考官网
属性 GridLayout参数:
layout
类型:Array
必需:true
这是网格的初始布局。
值必须是 Object 项的Array。 每个项目必须有 i,x,y,w 和 h proprties。 有关详细信息,请参阅 GridItem 文档 below。
colNum
类型:Number
必需:false
默认值:12
表示网格有多少列。
这个值应该是一个的自然数。
rowHeight
类型:Number
必需:false
默认值:150
表示单个行的高度以像素为单位。
maxRows
类型:Number
必需:false
默认值:Infinity
表示网格中的最大行数。
margin
类型:Array
必需:false
默认值:[10, 10]
表示网格的元素的边距是多少。
值必须是 Number的两个元素 Array。 每个值都用像素表示。 第一个元素是水平的margin,第二个元素是垂直边。
isDraggable
类型:Boolean
必需:false
默认值:true
表示网格的项是否可以拖动。
isResizable
类型:Boolean
必需:false
默认值:true
表示网格的项是否可以调整大小。
isMirrored
类型:Boolean
必需:false
默认值:false
表示是否应该反转 rtl/ltr。
autoSize
类型:Boolean
必需:false
默认值:true
表示容器高度是否应增大并收缩以适应内容。
verticalCompact
类型:Boolean
必需:false
默认值:true
表示布局是否应垂直为 compact。
useCssTransforms
类型:Boolean
必需:false
默认值:true
表示是否应使用 CSS transition-property: transform,否则是postion定位;。
属性GridItem参数
i
类型:String
必需:true
这是项的唯一标识符。
x
类型:Number
必需:true
表示项( 在哪个列中放置它)的初始水平位置。
值必须是一个整数。
y
类型:Number
必需:true
表示项( 应放置在哪一行)的初始垂直位置。
值必须是一个整数。
w
类型:Number
必需:true
表示项的初始宽度。
值是一个与 colWidth 相乘的数字。
h
类型:Number
必需:true
表示项的初始高度。
值是一个与 rowHeight 相乘的数字。
minW
类型:Number
必需:false
默认值:1
表示项的最小宽度。 如果 w 将小于 minW,那么 w 将被设置为 minW。
值是一个与 colWidth 相乘的数字。
minH
类型:Number
必需:false
默认值:1
表示什么是项的最小 hieght。 如果 h 将小于 minH,那么 h 将被设置为 minH。
值是一个与 rowHeight 相乘的数字。
maxW
类型:Number
必需:false
默认值:Infinity
表示项的最大宽度。 如果 w 大于 maxW,那么 w 将被设置为 maxW。
值是一个与 colWidth 相乘的数字。
maxH
类型:Number
必需:false
默认值:Infinity
表示什么是项的最大高度。 如果 h 大于 maxH,那么 h 将被设置为 maxH。
值是一个与 rowHeight 相乘的数字
isDraggable
类型:Boolean
必需:false
默认值:null
表示项是否可以拖动。
如果默认值为 null,则从父值继承。
isResizable
类型:Boolean
必需:false
默认值:null
表示项是否可以调整大小。
如果默认值为 null,则从父值继承。
dragIgnoreFrom
类型:String
必需:false
默认值:'a, button'
表示项的哪些元素不应触发项的拖动事件。
值为 css-like 选择器字符串。
dragAllowFrom
类型:String
必需:false
默认值:null
表示项的哪些元素应触发项的拖动事件。
值为 css-like 选择器字符串。
如果 null 可以拖动,则可以拖动项的任何( 排除 dragIgnoreFrom ) 元素。
resizeIgnoreFrom
类型:String
必需:false
默认值:'a, button'
表示项的哪些元素不应触发项的大小调整事件。
值为 css-like 选择器字符串。
上面的属性需要注意的是:
- w宽度时表示占据栅格的数比如: 1/12 2/12 3/12 (12是colNum)
- 在gridItem里w+x的最大和不应该超过colNum,否则会不生效
- verticalCompact表示的是垂直紧凑型布局,意思是当每一个gridItem上方没有其>他栅格时,总会向上靠拢
- useCssTransforms为true时使用c3属性translate3D实现平移,为false是采用的定位实现平移
好了,总结上面的内容:
现在有一个需求,当点击按钮的时候,重新布局页面上的栅格系统:
具体实现思路无非就是重新给gridItem赋值,参数可以自定义,但是要注意到校验参数,w与x的值是不能为小数的,因为他们代表的是栅格数,表现到页面上:
栅格数 * 每一个栅格的宽度
layoutGridItem(){
//出入的是对象
// let config = {
// i: 0,
// sizeObj: {
// w: 2,
// h: 5
// },
// positionObj: {
// x: 2,
// y: 4
// }
// }
let config = [{
i: 0,
sizeObj: {
w: 2,
h: 5
},
positionObj: {
x: 2,
y: 4
},
},{
i: 2,
sizeObj: {
w: 2,
h: 5
},
positionObj: {
x: 2,
y: 4
}
}]
//判断传入的参数是对象,还是数组
if(Object.prototype.toString.call(config) == "[object Object]") {
//校验参数
try{
let xString = config.positionObj.x + ""
let wString = config.sizeObj.w + ""
//判断传入的参数是否是小数
if(xString.includes(".") || wString.includes(".")) {
throw new Error("x 与 w参数不能是小数")
}
//判断x与w的和是否大于栅格数
if(config.positionObj.x + config.sizeObj.w > this.colNum) {
throw new Error("x 与 w之和不能大于栅格数")
}
}catch(e) {
console.log(e)
return
}
//设置新的布局格式
this.verticalCompact = false
this.layout.forEach(item => {
if(item.i == config.i) {
item.h = config.sizeObj.h
item.w = config.sizeObj.w
item.x = config.positionObj.x
item.y = config.positionObj.y
console.log(item.x,item.y,item.h,item.w)
}
})
}
if(Object.prototype.toString.call(config) == "[object Array]") {
//校验参数
try{
config.forEach(_ => {
let xString = _.positionObj.x + ""
let wString = _.sizeObj.w + ""
//判断传入的参数是否是小数
if(xString.includes(".") || wString.includes(".")) {
throw new Error("x 与 w参数不能是小数")
}
//判断x与w的和是否大于栅格数
if(_.positionObj.x + _.sizeObj.w > this.colNum) {
throw new Error("x 与 w之和不能大于栅格数")
}
})
}
catch(e) {
console.log(e)
return
}
this.verticalCompact = false
this.layout.forEach(item => {
config.forEach(_ => {
if(item.i == _.i) {
item.h = _.sizeObj.h
item.w = _.sizeObj.w
item.x = _.positionObj.x
item.y = _.positionObj.y
console.log(item.x,item.y,item.h,item.w)
}
})
})
}
}
完整源码:
<template>
<div class="layout">
<grid-layout
:layout.sync="layout"
:col-num="colNum"
:row-height="30"
:is-draggable="true"
:is-resizable="true"
:vertical-compact="verticalCompact"
:margin="[10, 10]"
:use-css-transforms="false"
class="hoverStyle">
<grid-item v-for="item in layout" :key="item.i"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
:i="item.i"
style="border: 1px solid #fff">
{{item.i}}
</grid-item>
</grid-layout>
<button @click="layoutGridItem">点击</button>
</div>
</template>
<script>
import VueGridLayout from 'vue-grid-layout';
export default {
components: {
GridLayout: VueGridLayout.GridLayout,
GridItem: VueGridLayout.GridItem
},
data(){
return {
layout: [
{"x":0,"y":0,"w":2,"h":2,"i":"0"},
{"x":2,"y":0,"w":2,"h":4,"i":"1"},
{"x":4,"y":0,"w":2,"h":5,"i":"2"},
],
verticalCompact: true,
colNum: 12 //栅格数
}
},
methods: {
layoutGridItem(){
//出入的是对象
// let config = {
// i: 0,
// sizeObj: {
// w: 2,
// h: 5
// },
// positionObj: {
// x: 2,
// y: 4
// }
// }
let config = [{
i: 0,
sizeObj: {
w: 2,
h: 5
},
positionObj: {
x: 2,
y: 4
},
},{
i: 2,
sizeObj: {
w: 2,
h: 5
},
positionObj: {
x: 2,
y: 4
}
}]
//判断传入的参数是对象,还是数组
if(Object.prototype.toString.call(config) == "[object Object]") {
//校验参数
try{
let xString = config.positionObj.x + ""
let wString = config.sizeObj.w + ""
//判断传入的参数是否是小数
if(xString.includes(".") || wString.includes(".")) {
throw new Error("x 与 w参数不能是小数")
}
//判断x与w的和是否大于栅格数
if(config.positionObj.x + config.sizeObj.w > this.colNum) {
throw new Error("x 与 w之和不能大于栅格数")
}
}catch(e) {
console.log(e)
return
}
//设置新的布局格式
this.verticalCompact = false
this.layout.forEach(item => {
if(item.i == config.i) {
item.h = config.sizeObj.h
item.w = config.sizeObj.w
item.x = config.positionObj.x
item.y = config.positionObj.y
console.log(item.x,item.y,item.h,item.w)
}
})
}
if(Object.prototype.toString.call(config) == "[object Array]") {
//校验参数
try{
config.forEach(_ => {
let xString = _.positionObj.x + ""
let wString = _.sizeObj.w + ""
//判断传入的参数是否是小数
if(xString.includes(".") || wString.includes(".")) {
throw new Error("x 与 w参数不能是小数")
}
//判断x与w的和是否大于栅格数
if(_.positionObj.x + _.sizeObj.w > this.colNum) {
throw new Error("x 与 w之和不能大于栅格数")
}
})
}
catch(e) {
console.log(e)
return
}
this.verticalCompact = false
this.layout.forEach(item => {
config.forEach(_ => {
if(item.i == _.i) {
item.h = _.sizeObj.h
item.w = _.sizeObj.w
item.x = _.positionObj.x
item.y = _.positionObj.y
console.log(item.x,item.y,item.h,item.w)
}
})
})
}
}
}
}
</script>
<style lang="scss">
.layout {
background: #999;
height: 500px;
}
.hoverStyle {
border: 1px solid #999;
// &:hover {
// border: 1px solid blue;
// }
}
</style>