基于特定的应用场景,需要在页面中以网格的方式,实现目标组件在网格中可以进行拖拉拽、修改大小等交互。本章开始分享如何一步步从代码设计,最后到如何在 NPM 上发布。
请大家动动小手,给我一个免费的 Star 吧~
大家如果发现了 Bug,欢迎来提 Issue 哟~
特别说明一下,此组件是基于 CSS 的 display: grid 的,并非全能型拖拉拽交互,grid 不支持的基本就是不支持的,此组件的目标是达到一些简易的网格布局拖拉拽交互。
效果图
拖动
调整大小
拖入
嵌套
有限的嵌套
项目结构
项目结构是基于另外一个项目 konva-designer-sample,特别说一下需要关注的部分:
└─ dist - 构建的组件库文件
└─ docs - 构建的在线示例网站
└─ src
└─ demo
│ └─ App.vue - 在线示例页面
└─ lib
└─ components
└─ GridDragResize - 组件目录
└─ GridDragResize.vue - 组件
└─ GridDragResizeItem.vue - 子组件
└─ index.ts - 组件入口
└─ style.less - 组件样式
└─ types.ts - 组件配套类型声明
└─ main.ts - 在线示例代码入口
└─ index.html - 在线示例HTML入口
└─ package.json - 库信息
└─ tsconfig.build.json - 用于构建组件库配套的类型声明文件
└─ vite.config.ts - 构建配置
使用方式
直接先看看组件的使用方式:
src/demo/App.vue
<script setup lang="ts">
import {
ref, h, type Ref } from 'vue'
// 组件
import {
GridDragResize } from '@/lib/components/GridDragResize'
// 组件配套类型声明
import type {
GridDragResizeProps } from '@/lib/components/GridDragResize/types'
// 组件数据结构
const children: Ref<GridDragResizeProps['children']> = ref([
{
dragHandler: '.demo-item>button',
render: () => h('div', {
class: "demo-item", style: {
background: '#eb9c64' } }, [h('button', 'drag handler')])
},
{
columnStart: 2,
draggable: false,
render: () => h('div', {
class: "demo-item", style: {
background: '#ff8789' } }, 'disable drag')
},
{
rowStart: 2,
columnStart: 2,
render: () => h('div', {
class: "demo-item", style: {
background: '#554e4f' } }, '1')
},
{
rowStart: 2,
rowEnd: 4,
columnStart: 4,
columnEnd: 5,
render: () => h('div', {
class: "demo-item", style: {
background: '#8fbf9f' } }, '2')
},
{
rowStart: 4,
rowEnd: 6,
columnStart: 2,
columnEnd: 4,
render: () => h('div', {
class: "demo-item", style: {
background: '#346145' } }, '3')
},
{
rowStart: 4,
rowEnd: 5,
columnStart: 1,
columnEnd: 2,
render: () => h('div', {
class: "demo-item", style: {
background: '#c2baa6' } }, '4')
},
])
</script>
<template>
<div class="page">
<!-- 组件使用 -->
<GridDragResize :columns="4" :rows="5" :gap="10" :row-size="100" :readonly="false" :children="children">
</GridDragResize>
<!-- 组件数据结构 实时状态 -->
<div v-html="JSON.stringify(children, null, 2).replace(/\n/g,