更新记录

1.0.1(2025-09-26)

  • 添加拖拽开始事件拦截功能
  • 添加item-click事件处理
  • 为默认网格项添加删除按钮样式配置

1.0.0(2025-09-26)

v1.0.0

  • 初始版本发布

平台兼容性

uni-app(4.66)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟

liaction-grid-drag

基于Vue 3的可拖拽网格组件,提供灵活的拖拽排序、项目管理功能,适用于UniApp项目。

特性

  • 支持两种拖拽模式:移位(shift)和交换(swap)
  • 可自定义网格布局(列数、间距、内边距等)
  • 支持固定项目(不可拖拽)
  • 内置删除功能,支持确认对话框
  • 支持添加项目功能
  • 丰富的样式自定义选项
  • 响应式设计,自适应窗口大小
  • 提供完整的事件回调机制
  • 支持项目级别的样式覆盖

基本用法

<template>
  <view class="container">
    <liaction-grid-drag
      :items="gridItems"
      :columns="3"
      :draggable="true"
      :drag-mode="'shift'"
      :show-delete-button="true"
      :show-add-slot="true"
      :useCustomDeleteModal="useCustomDeleteModal"
      @sortEnd="onSortEnd"
      @add-item="onAddItem"
      @delete-item="onDeleteItem"
      @item-click="onItemClick"
      @show-delete-modal="onShowDeleteModal"
    >
      <template #item="{ item, index }">
        <view style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;">
          <image :src="item.icon" mode="aspectFit" style="width: 50%; height: 50%;" />
          <text>{{ item.name }}</text>
        </view>
      </template>
    </liaction-grid-drag>
  </view>
</template>

<script>
export default {
  data() {
    return {
      gridItems: [
        { id: '1', name: '项目1', icon: '/static/icons/1.png' },
        { id: '2', name: '项目2', icon: '/static/icons/2.png' },
        { id: '3', name: '项目3', icon: '/static/icons/3.png' },
        { id: '4', name: '项目4', icon: '/static/icons/4.png' },
        { id: '5', name: '项目5', icon: '/static/icons/5.png' }
      ],
      useCustomDeleteModal: false
    }
  },
  methods: {
    onSortEnd(items) {
      this.gridItems = items;
      console.log('排序结果:', items);
    },
    onAddItem() {
      const newItem = {
        id: Date.now().toString(),
        name: `新项目${this.gridItems.length + 1}`,
        icon: `/static/icons/${Math.floor(Math.random() * 9) + 1}.png`
      };
      this.gridItems.push(newItem);
    },
    onDeleteItem({ item, index }) {
      this.gridItems.splice(index, 1);
    },
    onItemClick({ item, index }) {
      console.log('点击了项目:', item, '索引:', index);
    },
    onShowDeleteModal({ item, index, confirm, cancel }) {
      // 显示自定义删除确认弹窗
      // 用户确认后调用 confirm()
      // 用户取消后调用 cancel()
    }
  }
}
</script>

<style>
.container {
  padding: 20px;
}
</style>

Props

属性名 类型 默认值 说明
columns Number 3 网格列数,必须为正整数
items Array [] 网格项目数据数组
gap Number 10 项目间距(像素),必须为非负数
padding Number 10 容器内边距(像素),必须为非负数
dragMode String 'shift' 拖拽模式,可选值:'shift'(移位)、'swap'(交换)
draggable Boolean false 是否允许拖拽
aspectRatio Number 1 项目宽高比,必须大于0
showDeleteButton Boolean false 是否显示删除按钮
showAddSlot Boolean false 是否显示添加按钮
maxItemCount Number Infinity 最大项目数量限制
maxHeight Number Infinity 容器最大高度(像素)
minHeight Number 100 容器最小高度(像素)
useDefaultItems Boolean false 是否使用默认项目数据
defaultItemCount Number 9 默认项目数量
defaultItemsDraggable Boolean true 默认项目是否可拖拽
defaultItemsDeletable Boolean true 默认项目是否可删除
useCustomDeleteModal Boolean false 是否使用自定义删除弹窗

样式相关属性

属性名 类型 默认值 说明
itemBgColor String '#409eff' 项目背景色
fixedItemBgColor String '#909399' 固定项目背景色
addSlotBgColor String '#f0f2f5' 添加按钮背景色
itemTextColor String 'white' 项目文本颜色
addSlotTextColor String '#606266' 添加按钮文本颜色
itemBorderRadius Number 8 项目圆角(像素)
itemTextSize Number 14 项目文本大小(像素)
itemTextWeight String/Number 'normal' 项目文本粗细
itemTextFontFamily String 'sans-serif' 项目文本字体
itemTextStyle Object {} 项目文本额外样式

删除按钮相关属性

属性名 类型 默认值 说明
deleteBtnSize Number 24 删除按钮大小(像素)
deleteBtnBgColor String '#ff0000' 删除按钮背景色
deleteBtnTextColor String '#fff' 删除按钮文本颜色
deleteBtnFontSize Number 12 删除按钮字体大小
deleteBtnText String '×' 删除按钮文本
deleteBtnMaxDigitsLength Number 2 数字类型删除按钮文本最大长度
deleteBtnMaxLength Number 1 非数字类型删除按钮文本最大长度

删除确认对话框属性

属性名 类型 默认值 说明
deleteConfirmTitle String '提示' 确认对话框标题
deleteConfirmMessage String '确定要删除这个项目吗?' 确认对话框消息
deleteConfirmConfirmText String '确定' 确认按钮文本
deleteConfirmCancelText String '取消' 取消按钮文本

滚动条相关属性

属性名 类型 默认值 说明
scrollbarWidth Number 6 滚动条宽度(像素),必须大于等于2
scrollbarTrackColor String '#f5f5f5' 滚动条轨道颜色
scrollbarThumbColor String '#ccc' 滚动条滑块颜色
scrollbarThumbHoverColor String '#aaa' 滚动条滑块悬停颜色
scrollbarRadius Number 3 滚动条圆角(像素)

Item 数据结构

每个网格项目可以包含以下属性:

属性名 类型 说明
id String/Number 项目唯一标识
name String 项目名称(默认显示文本)
draggable Boolean 该项是否可拖拽(覆盖全局设置)
deletable Boolean 该项是否可删除
fixed Boolean 该项是否固定(固定项不可拖拽)
deleteBtnSize Number 该项删除按钮大小(覆盖全局设置)
deleteBtnBgColor String 该项删除按钮背景色(覆盖全局设置)
deleteBtnTextColor String 该项删除按钮文本颜色(覆盖全局设置)
deleteBtnFontSize Number 该项删除按钮字体大小(覆盖全局设置)
deleteBtnText String 该项删除按钮文本(覆盖全局设置)
deleteBtnMaxDigitsLength Number 该项数字类型删除按钮文本最大长度(覆盖全局设置)
deleteBtnMaxLength Number 该项非数字类型删除按钮文本最大长度(覆盖全局设置)
其他自定义属性 任意 自定义数据,可在插槽中使用

事件

事件名 说明 回调参数
sortEnd 排序完成时触发 items: 排序后的项目数组
sort-complete 排序完成时触发(与sortEnd相同,兼容性别名) items: 排序后的项目数组
update:items 项目数组更新时触发 items: 更新后的项目数组
add-item 点击添加按钮时触发
delete-item 确认删除项目时触发 { item: 删除的项目, index: 删除的索引 }
delete-confirmed 确认删除项目时触发(与delete-item相同,用于明确区分确认状态) { item: 删除的项目, index: 删除的索引 }
delete-canceled 取消删除项目时触发 { item: 取消删除的项目, index: 项目索引 }
drag-start 开始拖拽时触发 { item: 拖拽的项目, index: 项目索引 }
drag-end 结束拖拽时触发 { item: 拖拽的项目, index: 项目索引 }
item-click 点击项目时触发 { item: 点击的项目, index: 项目索引 }
show-delete-modal 使用自定义删除弹窗时触发(需要设置useCustomDeleteModal为true) { item: 要删除的项目, index: 项目索引, confirm: 确认回调, cancel: 取消回调 }

插槽

插槽名 说明 插槽参数
item 自定义项目内容 { item: 项目数据, index: 项目索引, isDragging: 是否正在拖拽, isDraggable: 是否可拖拽 }
delete-button 自定义删除按钮 { item: 项目数据, index: 项目索引 }
addSlot 自定义添加按钮

部分示例

基本用法

<liaction-grid-drag
    :useDefaultItems="true"
/>

基本用法示例

固定项目示例

<template>
  <liaction-grid-drag
    :items="gridItems"
    :columns="4"
    :draggable="true"
    :show-delete-button="true"
  />
</template>

<script>
export default {
  data() {
    return {
      gridItems: [
        { id: '1', name: '可拖拽项目', draggable: true },
        { id: '2', name: '固定项目', fixed: true }, // 通过fixed属性固定项目
        { id: '3', name: '可拖拽项目2', draggable: true },
        { id: '4', name: '不可删除', deletable: false }
      ]
    }
  }
}
</script>

固定项目示例

自定义项目样式

<template>
    <liaction-grid-drag :items="gridItems" :columns="3" :gap="15" itemBgColor="#67c23a" itemTextColor="#fff"
        itemBorderRadius="12">
        <template #item="{ item, isDragging }">
            <view class="custom-item" :class="{ 'dragging': isDragging }">
                <image :src="item.image" mode="aspectFit" class="item-image" />
                <text class="item-title">{{ item.title }}</text>
                <text class="item-desc">{{ item.description }}</text>
            </view>
        </template>
    </liaction-grid-drag>
</template>

<script>
    export default {
        data() {
            return {
                gridItems: [
                    {
                        image: '/static/icons/1.png',
                        title: 'Item 1',
                        description: 'Description 1'
                    },
                    {
                        image: '/static/icons/2.png',
                        title: 'Item 2',
                        description: 'Description 2'
                    },
                    {
                        image: '/static/icons/3.png',
                        title: 'Item 3',
                        description: 'Description 3'
                    },
                    {
                        image: '/static/icons/4.png',
                        title: 'Item 4',
                        description: 'Description 4'
                    },
                    {
                        image: '/static/icons/5.png',
                        title: 'Item 5',
                        description: 'Description 5'
                    }
                ],
            }
        }
    }
</script>

<style scoped>
    .custom-item {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 10px;
        box-sizing: border-box;
    }

    .item-image {
        width: 60px;
        height: 60px;
        margin-bottom: 8px;
    }

    .item-title {
        font-weight: bold;
        margin-bottom: 4px;
    }

    .item-desc {
        font-size: 12px;
        text-align: center;
    }

    .dragging {
        opacity: 0.8;
    }
</style>

自定义项目样式示例

常见问题与解决方案

问题:拖拽时项目位置不正确

解决方法:确保没有在样式中覆盖组件内部的定位样式,特别是movable-view元素的定位属性。

问题:固定项目被意外移动

解决方法:检查项目数据中fixed属性是否正确设置,确保固定项目的draggable属性为false。

问题:滚动条样式不符合预期

解决方法:通过自定义滚动条相关props来调整样式,或者在全局样式中定义相应的滚动条样式覆盖。

问题:在小屏幕设备上拖拽不流畅

解决方法:可以适当增加DRAG_THRESHOLD值来减少计算频率,或者减少同时显示的项目数量。

注意事项

  1. 组件使用了Vue 3的Composition API,确保您的项目支持Vue 3
  2. 组件依赖UniApp的movable-area和movable-view组件,确保在非UniApp环境中适当适配
  3. 对于大量数据(如超过50项),可能需要优化性能或考虑虚拟列表
  4. 拖拽操作可能在某些低性能设备上有延迟,建议根据实际场景调整参数
  5. 在自定义样式时,避免直接修改组件内部的类名样式,建议使用插槽和自定义类
  6. 当设置fixed: true属性时,组件会自动将该项的draggable属性设置为false
  7. 自定义删除弹窗功能需要同时设置useCustomDeleteModal: true并监听show-delete-modal事件
  8. 组件内部使用_uniqueKey作为项目的唯一标识,在事件回调中会自动过滤掉该属性

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。