当前位置: 首页 > news >正文

vue中的 拖拽

拖拽总结

实现方式特点适用场景
HTML5 原生拖拽 API✅ 直接使用 dataTransfer 进行数据传输
✅ 兼容性好(大部分浏览器支持)
✅ 适合简单的拖拽场景
低代码平台、表单生成器、组件拖拽
Vue/React 组件库(如 Vue Draggable、SortableJS)✅ 提供更丰富的交互效果
✅ 支持列表排序、拖拽嵌套
❌ 依赖额外的库
复杂拖拽,如列表排序、树状结构
CSS 仅视觉拖拽(无交互)✅ 仅改变视觉位置,无数据交互
❌ 无法存储拖拽数据
简单 UI 动画

目录

拖拽总结

HTML5 原生拖拽API(Drag and Drop API)

 相关代码知识点:

e.dataTransfer.setData(format, data):

e.dataTransfer.effectAllowed = 'copy';   设置拖拽的效果,表示拖拽的操作类型:

@dragover.prevent

@drop="onDropCanvas"

e.dataTransfer.getData('text/plain');:获取拖拽的数据(之前 dragstart 事件 setData 的数据)。

JSON.parse(itemData);:解析 JSON 数据,得到组件信息。

例子 —— 简易拖拽代码(H5: dataTransfer.setData + store 维护数据)

本例分析:

拖拽流程:

两种拖拽方式:


HTML5 原生拖拽API(Drag and Drop API)

分为:拖拽源 和 拖拽目标。适用于vue低代码开发。(若要 拖拽嵌套 或 复杂排序,考虑 Vue Draggable(基于 SortableJS))

拖拽源 -> 拖拽开始dragstart

  • 设置 dataTransfer.setData() 存储拖拽的数据。

  • 设置 effectAllowed 允许的拖拽行为。

  • draggable="true":启用 HTML5 拖拽。

  • @dragstart 触发 onDragStart(),存储数据。

  • e.dataTransfer.setData('text/plain', JSON.stringify(item))drop 端获取拖拽的数据。

拖拽过程中dragover)——(事件:dragover,即 拖拽对象悬停在目标上时触发)

  • 必须 preventDefault(),否则 drop 事件不会触发

拖拽目标 -> 拖拽结束drop

  • 读取 dataTransfer.getData() 获取拖拽的数据。

  • 在目标区域渲染组件。

  • @dragover.prevent阻止默认行为,允许 drop 触发。(默认情况下,浏览器不允许drop)

  • @drop="onDropCanvas":处理组件释放到画布的逻辑。

  • e.dataTransfer.getData('text/plain') 读取拖拽的数据。

  • canvasComponents.value.push() 添加组件到画布。

 相关代码知识点:
  • e.dataTransfer.setData(format, data)
    • 作用:设置拖拽时传输的数据,这样在 drop 事件时可以取回。

    • text/plain:表示数据格式为纯文本字符串(不同浏览器可能要求必须是文本格式)。

    • JSON.stringify(item):将 item(对象)转换为字符串存储,方便 drop 事件解析。

        ⚠ 注意:不设置 setData,某些浏览器可能无法正确触发 drop 事件。

  • e.dataTransfer.effectAllowed = 'copy';   设置拖拽的效果,表示拖拽的操作类型:
    • 'copy':表示复制(不会影响原始数据)。

    • 'move':表示移动(可能会删除原始数据)。

    • 'link':表示创建链接

  • @dragover.prevent
    • 事件:dragover(拖拽对象悬停在目标上时触发)。

    • prevent:阻止默认行为(默认情况下,浏览器不允许 drop)。

  • @drop="onDropCanvas"
    • 事件:drop(用户松开鼠标时触发)。

    • 作用:获取拖拽的数据;将组件添加到画布;更新 UI 状态。

  • e.preventDefault();:避免浏览器默认行为(如打开文件)。

  • e.dataTransfer.getData('text/plain');:获取拖拽的数据(之前 dragstart 事件 setData 的数据)。
  • JSON.parse(itemData);:解析 JSON 数据,得到组件信息。
  • store.addComponentToCanvas(component);:将组件添加到画布中。


例子 —— 简易拖拽代码(H5 dataTransfer.setData + store 维护数据)

<!-- test.vue -->
<script setup>
import e from 'cors';
import { store } from './store.js';

const componentList  = [
    { id: 1, type: 'Container' },
    { id: 2, type: 'Text'},
];
// 拖拽开始事件
const onDragStart = (e, item) => {
    e.dataTransfer.setData('text/plain', JSON.stringify(item)); // 设置拖拽开始 传输的数据,纯文本 字符串,将 item 对象 转为字符串存储,便于后续drop解析
    e.dataTransfer.effectAllowed = 'copy';      // 拖拽效果,拖拽类型。copy 指 复制,不影响原数据;move,表 移动,可能会删原数据;link,表示创建链接
    store.setDragItem(item, true);   // 记录当前正在拖拽的组件信息。true表示从组件库拖拽。(区分,从组件库 拖拽,和 画布内拖拽)
}  

const onDropCanvas = () => {
    // const itemData = e.dataTransfer.getData('text/plain');   // 获取拖拽的数据
    // if(!itemData) return;
    // const item = JSON.parse(itemData);  // 将字符串转为对象
    console.log("drop拖拽开始")
    store.dropToCanvas(null);
}
</script>
<template>
    <div class="app1">
        <h3>组件库(可拖动)</h3>
        <div 
            v-for="(item, index) in componentList"
            :key="item.id"
            class="draggable-item"
            draggable="true"
            @dragstart="onDragStart($event, item)"
        >
            {{ item.type }}
        </div>
        <h3>画布区域</h3>
        <div class="canvas"
            @dragover.prevent
            @drop="onDropCanvas"
        >
        <!--@dropover.prevent 阻止默认行为。(默认情况下,浏览器不允许drop)  -->
            <div v-for="(item, index) in store.treeData" :key="item.id" class="draggable-item">
                {{ item.type }}-{{ item.id }}
            </div>
        </div>
    </div>
</template>
<style scoped lang='scss'>
.app1 {
    padding: 20px;
    .draggable-item {
        border: 1px solid #ccc;
        text-align: center;
        width: 300px;
        height: 100px;
        line-height: 100px;
        background:pink;
    }
    .canvas {
        border: 2px dashed #ccc;
        width: 500px;
        height: 300px;
        margin-top:20px;
        // background: skyblue;
    }
}
</style>
// store.js
import { reactive } from 'vue'
export const store = reactive({
    treeData: [],   // 画布中的组件数据
    dragItem: null, // 当前拖拽的组件
    isRawComponents: false,   // 是否是组件库的
    
    // 设置当前拖拽的组件
    setDragItem(item, isRawComponents = false){
        this.dragItem = item;
        this.isRawComponents = isRawComponents;
        console.log("设置当前拖拽的组件。")
    },

    // 拖拽到画布中
    dropToCanvas() {
        if(!this.dragItem) return;

        const newItem = {
            id: Date.now(),
            type: this.dragItem.type,
            children: [],   // 支持未来qiantao
        };

        this.treeData.push(newItem);
        console.log("拖拽到画布。")
        this.dragItem = null;   // 清空拖拽数据
    }
})

本例分析:

通过 全局 store 维护了拖拽数据,而不是使用 dataTransfer.getData 来获取拖拽数据。

  • onDragStart 事件

    • 当用户开始拖拽组件库中的组件时,会执行 onDragStart 方法。

    • onDragStart 里除了使用 e.dataTransfer.setData 之外,还调用了 store.setDragItem(item, true),这个方法的作用是在全局的 store 里记录当前拖拽的组件信息,并标记它是从组件库拖拽的(true)。

  • onDropCanvas 事件

    • 当拖拽到画布区域并触发 onDropCanvas 时,并没有使用 e.dataTransfer.getData 获取数据。

    • 取而代之的是 store.dropToCanvas(null);,这个方法直接从 store 里获取之前存储的 dragItem 并添加到 treeData

  • dropToCanvas 方法

    • dropToCanvas 方法检查 this.dragItem 是否存在,如果存在,就创建一个新的 newItem 并添加到 treeData

    • 这样,数据传递并没有通过 dataTransfer.getData,而是通过全局 store 变量来完成的。


拖拽流程:
  1. onDragStart(e, item)store.setDragItem(item, true); 记录拖拽的组件数据。

  2. onDropCanvas()store.dropToCanvas(null); 获取 store.dragItem 并添加到 treeData

两种拖拽方式:

dataTransfer.setDatagetData 适用于不同的页面或应用之间的数据传递,但

②在同一个 Vue 组件的状态管理下,getData部分 完全可以使用 Vue 的 store 机制来管理拖拽数据。

②用 Vue 的 store 机制来管理拖拽数据优势

  • 避免 dataTransfer.getData 只能存储字符串的限制,直接在 store 里存储对象数据,不用手动 JSON.stringifyJSON.parse

  • 数据可以跨多个事件存储,即使拖拽过程中发生变化(比如鼠标移动到不同位置),仍然可以获取正确的数据。

  • 更方便管理拖拽状态,比如可以在 store 里添加 isDragging 状态,防止意外行为。

http://www.dtcms.com/a/108016.html

相关文章:

  • @ComponentScan注解详解:Spring组件扫描的核心机制
  • 【力扣hot100题】(037)翻转二叉树
  • 每日一题---买卖股票的最好时机(一)、(二)
  • 【每日算法】Day 15-1:哈希表与布隆过滤器——海量数据处理与高效检索的核心技术(C++实现)
  • ollama本地部署大模型(命令行)
  • Eclipse IDE
  • 基本元素定位(findElement方法)
  • 【嵌入式Linux】U-Boot源码分析
  • JMeter接口自动化发包与示例
  • Windows连接服务器Ubuntu_MobaXterm
  • 【Mysql】基础(函数,约束,多表查询,事务)
  • PHP语言基础
  • 深入解析C++类:面向对象编程的核心基石
  • 前端css+html面试题
  • 面向对象分析与设计的多过程多层级实现
  • Generic Mapping Tools(GMT):开源的地球、海洋和行星科学的工具箱、Python与matlab包
  • 从零构建大语言模型全栈开发指南:第四部分:工程实践与部署-4.3.2知识库增强与外部API集成(代码示例:HTTP节点与检索增强生成)
  • uniapp 微信小程序 使用ucharts
  • 实战打靶集锦-36-Deception
  • 封装可拖动弹窗(vue jquery引入到html的版本)
  • SQL语句(一)—— DDL
  • [Lc6_记忆化搜索] 最长递增子序列 | 矩阵中的最长递增路径
  • 【大模型系列篇】大模型基建工程:使用 FastAPI 构建 SSE MCP 服务器
  • 14-SpringBoot3入门-MyBatis-Plus之CRUD
  • 树莓派超全系列文档--(15)无需交互使用raspi-config工具其二
  • clickhouse集群版本部署文档
  • jenkins 参数化发布到服务器 publish over ssh、label、Parameterized publishing
  • 基于DeepSeek、ChatGPT支持下的地质灾害风险评估、易发性分析、信息化建库及灾后重建
  • js实现一个可指定超时时间的异步函数重试机制
  • tomcat 目录结构组成