手撸 Grid 拖拽布局
最近有个需求需要实现自定义首页布局,需要将屏幕按照 6 列 4 行进行等分成多个格子,然后将组件拖拽对应格子进行渲染展示。
示例
对比一些已有的插件,发现想要实现产品的交互效果,没有现成可用的。本身功能并不是太过复杂,于是决定自己基于 vue 手撸一个简易的 Grid 拖拽布局。
完整源码在此,在线体验
概况 ​
需要实现 Grid 拖拽布局,主要了解这两个东西就行
- 拖放 API,关于拖放 API 介绍文章有很多 ,可以直接看 MDN 里拖放 API介绍,可以说很详细了。
- Grid 布局, Grid 布局与 Flex 布局很相似,但是 Grid 像是二维布局,Flex 则为一维布局,Grid 布局远比 Flex 布局强大。MDN 关于网格布局介绍
需要实现主要包含:
- 组件物料栏拖拽到布局容器
- 布局容器 Grid 布局
- 放置时是否重叠判断
- 拖拽时样式
- 放置后样式
- 容器内二次拖拽
拖放操作实现 ​
拖拽中主要使用到的事件如下
- 被拖拽元素事件:
| 事件 | 触发时刻 |
|---|---|
| dragstart | 当用户开始拖拽一个元素或选中的文本时触发。 |
| drag | 当拖拽元素或选中的文本时触发。 |
| dragend | 当拖拽操作结束时触发 |
- 放置容器事件:
| 事件 | 触发时刻 |
|---|---|
| dragenter | 当拖拽元素或选中的文本到一个可释放目标时触发。 |
| dragleave | 当拖拽元素或选中的文本离开一个可释放目标时触发。 |
| dragover | 当元素或选中的文本被拖到一个可释放目标上时触发。 |
| drop | 当元素或选中的文本在可释放目标上被释放时触发。 |
可拖拽元素 ​
让一个元素能够拖拽只需要给元素设置 draggable="true" 即可拖拽,拖拽事件 API 提供了 DataTransfer 对象,可以用于设置拖拽数据信息,但是仅仅只能 drop 事件中获取到。因为我们需要在拖拽中就需要获取到拖拽信息,用来显示拖拽时样式,所以需要自己处理这些信息存储起来,以便读取。
需要处理主要是,在拖拽时将 将当前元素信息设置到 dragStore 中,结束时清空当前信息。
<script setup lang="ts">
import { dragStore } from "./drag";
const props = defineProps<{
data: DragItem;
groupName?: string;
}>();...剩余内容已隐藏
手撸 Grid 拖拽布局
最近有个需求需要实现自定义首页布局,需要将屏幕按照 6 列 4 行进行等分成多个格子,然后将组件拖拽对应格子进行渲染展示。
示例
对比一些已有的插件,发现想要实现产品的交互效果,没有现成可用的。本身功能并不是太过复杂,于是决定自己基于 vue 手撸一个简易的 Grid 拖拽布局。
完整源码在此,在线体验
概况 ​
需要实现 Grid 拖拽布局,主要了解这两个东西就行
- 拖放 API,关于拖放 API 介绍文章有很多 ,可以直接看 MDN 里拖放 API介绍,可以说很详细了。
- Grid 布局, Grid 布局与 Flex 布局很相似,但是 Grid 像是二维布局,Flex 则为一维布局,Grid 布局远比 Flex 布局强大。MDN 关于网格布局介绍
需要实现主要包含:
- 组件物料栏拖拽到布局容器
- 布局容器 Grid 布局
- 放置时是否重叠判断
- 拖拽时样式
- 放置后样式
- 容器内二次拖拽
拖放操作实现 ​
拖拽中主要使用到的事件如下
- 被拖拽元素事件:
| 事件 | 触发时刻 |
|---|---|
| dragstart | 当用户开始拖拽一个元素或选中的文本时触发。 |
| drag | 当拖拽元素或选中的文本时触发。 |
| dragend | 当拖拽操作结束时触发 |
- 放置容器事件:
| 事件 | 触发时刻 |
|---|---|
| dragenter | 当拖拽元素或选中的文本到一个可释放目标时触发。 |
| dragleave | 当拖拽元素或选中的文本离开一个可释放目标时触发。 |
| dragover | 当元素或选中的文本被拖到一个可释放目标上时触发。 |
| drop | 当元素或选中的文本在可释放目标上被释放时触发。 |
可拖拽元素 ​
让一个元素能够拖拽只需要给元素设置 draggable="true" 即可拖拽,拖拽事件 API 提供了 DataTransfer 对象,可以用于设置拖拽数据信息,但是仅仅只能 drop 事件中获取到。因为我们需要在拖拽中就需要获取到拖拽信息,用来显示拖拽时样式,所以需要自己处理这些信息存储起来,以便读取。
需要处理主要是,在拖拽时将 将当前元素信息设置到 dragStore 中,结束时清空当前信息。
<script setup lang="ts">
import { dragStore } from "./drag";
const props = defineProps<{
data: DragItem;
groupName?: string;
}>();...剩余内容已隐藏