拖拽宫格vue-grid-layout详细应用及案例
文章目录
- 1、前言
- 2、安装
- 3、属性
- 4、事件
- 5、占位符样式修改
- 6、案例
1、前言
vue-grid-layout是一个适用于vue的拖拽栅格布局库,功能齐全,适用于拖拽+高度/宽度自由调节的布局需求,本文将讲述一些常用参数和事件,以及做一个同步拖拽的Demo。效果动态图如下:
2、安装
- vue2版本:
npm install vue-grid-layout --save
- vue3版本:
npm install vue-grid-layout@3.0.0-beta1 --save
3、属性
- GridLayout 容器:
属性名 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
layout | Array | 是 | - | 数据源,每一项必须有i, x, y, w 和 h属性 |
colNum | Int | 否 | 12 | 列数 |
rowHeight | Int | 否 | 150 | 每行的高度像素 |
maxRows | Int | 否 | Infinity | 最大行数 |
margin | Array | 是 | [10, 10] | 元素边距 |
isDraggable | Boolean | 否 | true | 是否可拖拽 |
isResizable | Boolean | 否 | true | 是否可调整大小 |
isMirrored | Boolean | 否 | false | 是否可镜像反转 |
autoSize | Boolean | 否 | true | 是否自动调整大小 |
verticalCompact | Boolean | 否 | true | 布局是否垂直压缩 |
preventCollision | Boolean | 否 | false | 防止碰撞,为true则元素只能拖动至空白处 |
useCssTransforms | Boolean | 否 | true | 是否使用CSS属性 transition-property: transform |
responsive | Boolean | 否 | false | 布局是否为响应式 |
breakpoints | Boolean | 否 | { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 } | 为响应式布局设置断点 |
cols | Boolean | 否 | { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 } | 设置每个断点对应的列数 |
- GridItem 子项:
属性名 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
i | string | 是 | - | 子项ID |
x | number | 是 | - | 元素位于第几列 |
y | number | 是 | - | 元素位于第几行 |
w | number | 是 | - | 初始宽度,值必须为colNum的倍数 |
h | number | 是 | - | 初始高度,值必须为rowHeight的倍数 |
minW | number | 否 | 1 | 元素最小宽度,值必须为colNum的倍数,如果w小于minW,则minW的值会被w覆盖 |
minH | number | 否 | 1 | 元素最小高度,值必须为rowHeight的倍数,如果h小于minH,则minH的值会被h覆盖 |
maxW | number | 否 | Infinity | 元素最大宽度,值必须为colNum的倍数,如果w大于maxW,则maxW的值会被w覆盖 |
maxH | number | 否 | Infinity | 元素最大高度,值必须为rowHeight的倍数,如果h大于maxH,则maxH的值会被h覆盖 |
isDraggable | Boolean | 否 | null | 是否可拖拽。如果值为null则取决于父容器 |
isResizable | Boolean | 否 | null | 是否可调整大小。如果值为null则取决于父容器 |
static | Boolean | 否 | false | 是否为静态的,无法拖拽、调整大小或被其他元素移动 |
dragIgnoreFrom | string | 否 | ‘a, button’ | 标识哪些子元素无法触发拖拽事件,值为css-like选择器 |
dragAllowFrom | string | 否 | null | 标识哪些子元素可以触发拖拽事件,值为css-like选择器,如果值为null则表示所有子元素 |
resizeIgnoreFrom | string | 否 | ‘a, button’ | 标识哪些子元素无法触发调整大小的事件,值为css-like选择器 |
4、事件
- GridLayout 容器:
事件名 | 描述 |
---|---|
layoutCreatedEvent | 对应Vue生命周期的created |
layoutBeforeMountEvent | 对应Vue生命周期的beforeMount |
layoutMountedEvent | 对应Vue生命周期的mounted |
layoutReadyEvent | 当完成mount中的所有操作时生成的事件 |
layoutUpdatedEvent | 布局更新或栅格元素的位置重新计算事件 |
breakpointChangedEvent | 断点更改事件,每次断点值由于窗口调整大小而改变 |
- GridItem 子项:
事件名 | 描述 |
---|---|
moveEvent | 移动时的事件 |
resizeEvent | 调整大小时的事件 |
movedEvent | 移动后的事件 |
resizedEvent | 调整大小后的事件 |
containerResizedEvent | 栅格元素/栅格容器更改大小的事件(浏览器窗口或其他) |
5、占位符样式修改
直接覆盖默认的class样式
.vue-grid-item.vue-grid-placeholder {background: red;opacity: 0.2;transition-duration: 100ms;z-index: 2;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;-o-user-select: none;user-select: none;
}.vue-grid-item.vue-grid-placeholder {background: green !important;
}
6、案例
注:本案例是按照vue3的写法
- HTML:
<div class="grid_box"><div class="left"><grid-layoutv-model:layout="layoutLeft":col-num="4":row-height="50":is-draggable="true":is-resizable="true":is-mirrored="false":vertical-compact="true":margin="[10, 10]":use-css-transforms="true"ref="gridLeftRef"><grid-itemv-for="item in layoutLeft":x="item.x":y="item.y":w="item.w":h="item.h":i="item.i":key="item.i"@resized="handleGridSync"@moved="handleGridSync"><div class="left_layout_item"><div class="del_btn" @click="deleteGrid(item.i)">删</div><span>{{ item.i }}</span></div></grid-item></grid-layout></div><div class="right"><grid-layoutv-model:layout="layoutRight":col-num="4":row-height="10":is-draggable="true":is-resizable="true":is-mirrored="false":vertical-compact="true":margin="[10, 10]":use-css-transforms="true"ref="gridRightRef"><grid-item v-for="item in layoutRight" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :i="item.i" :key="item.i"><div class="right_layout_item">{{ item.i }}</div></grid-item></grid-layout></div>
</div>
- 引入组件
import VueGridLayout from 'vue-grid-layout'
- 数据源:
const gridLeftRef = ref<any>()
const gridRightRef = ref<any>()const layoutLeft = ref([{ i: '1', x: 0, y: 0, w: 2, h: 2 },{ i: '2', x: 2, y: 0, w: 2, h: 2 },{ i: '3', x: 0, y: 0, w: 2, h: 2 },{ i: '4', x: 2, y: 0, w: 2, h: 2 }
])const layoutRight = ref([{ i: '1', x: 0, y: 0, w: 2, h: 2 },{ i: '2', x: 2, y: 0, w: 2, h: 2 },{ i: '3', x: 0, y: 0, w: 2, h: 2 },{ i: '4', x: 2, y: 0, w: 2, h: 2 }
])
- 处理方法:
// 处理Grid同步
const handleGridSync = () => {layoutLeft.value.forEach((item1) => {layoutRight.value.forEach((item2) => {if (item1.i === item2.i) {item2.x = item1.xitem2.y = item1.yitem2.w = item1.witem2.h = 2}})})gridLeftRef.value.layoutUpdate()gridLeftRef.value.updateHeight()gridRightRef.value.layoutUpdate()gridRightRef.value.updateHeight()
}// 创造Grid
const createGrid = () => {let maxH = 0layoutLeft.value.forEach((item) => {if (item.y > maxH) maxH = item.y})const uid = createUuid()layoutLeft.value.push({ i: uid, x: 0, y: maxH, w: 2, h: 2 })layoutRight.value.push({ i: uid, x: 0, y: maxH, w: 2, h: 2 })handleGridSync()
}// 删除Grid
const deleteGrid = (id: string) => {const idx1 = layoutLeft.value.findIndex((item1) => item1.i === id)layoutLeft.value.splice(idx1, 1)const idx2 = layoutRight.value.findIndex((item2) => item2.i === id)layoutRight.value.splice(idx2, 1)handleGridSync()
}
本次分享就到这儿啦,我是鹏多多,如果您看了觉得有帮助,欢迎评论,关注,点赞,转发,我们下次见~
往期文章
- Vue2全家桶+Element搭建的PC端在线音乐网站
- vue3+element-plus配置cdn
- 助你上手Vue3全家桶之Vue3教程
- 助你上手Vue3全家桶之VueX4教程
- 助你上手Vue3全家桶之Vue-Router4教程
- 超详细!Vue的九种通信方式
- 超详细!Vuex手把手教程
- 使用nvm管理node.js版本以及更换npm淘宝镜像源
- vue中利用.env文件存储全局环境变量,以及配置vue启动和打包命令
- 超详细!Vue-Router手把手教程
个人主页
- CSDN
- GitHub
- 简书
- 博客园
- 掘金