拖拽不够自由?Vue3 DnD它来了!

前言

众所周知,在React中有一款非常强大的拖拽库,叫React DnD,而Vue中,大部分都是类似于vue.draggable等拖拽排序的库,然而它并不能满足我们所有的需求,特别是应对一些自由拖拽或混合拖拽的场景(例如:低代码),它是很难做到的,所以vue3-dnd它来了!

React DnD

React DnD 是 Redux 核心作者 Dan Abramov 创造的一组 React 工具库,可以帮助您构建复杂的拖放接口,同时保持组件的解耦性。 React DnD 并没有提供一个排序或拖拽的组件,相反,它为您提供了所需的工具。

Vue3 DnD

vue3-dnd 是基于React DnD的核心程序实现的一组Vue composition-api,它提供了尽量与React DnD保持一致的api,便于我们去构建一个复杂、自由的拖拽功能。

安装

越来越多的人使用pnpm,所以我们也推荐你使用pnpm来进行安装,当然你也可以使用其它任意工具进行安装

pnpm install vue3-dnd react-dnd-html5-backend
# or
npm install vue3-dnd react-dnd-html5-backend

react-dnd-html5-backend 是一个React DnD 的插件,它提供了一个HTML5的拖放支持;你也可以使用react-dnd-touch-backend 提供移动端拖放支持。

得益于React DnD的优秀设计,我们可以直接使用它提供的backend,或者实现一个自己的backend,还可以使用 react-dnd-test-backend 来测试你的拖拽组件。

概念

React DnD创造了一些新的概念,如果第一次使用它的话,我们可能要提前了解它。

当然,你也可以先跳过这一部分,在你真正使用的时候再去了解它

项目(Items) 和 类型(Types)

React DnD 使用数据而不是视图作为拖拽实施。当您在屏幕上拖动某些东西时,我们不会说正在拖动组件或 DOM 节点。相反,我们说正在拖动某种类型项目

监视器(Monitors)

拖放本质上是有状态的。拖动操作正在进行中,或者没有。要么有当前类型和当前项目,要么没有。这种状态必须存在于某个地方。

对于每个需要跟踪拖放状态的组件,您可以定义一个收集函数,从监视器中提取状态;例如:

const [collect, drop] = useDrop({
  accept: 'Cell',
  collect: monitor => ({
    canDrop: monitor.canDrop(),
    hovered: monitor.isOver(),
  }),
})

连接器(Connectors)

连接器允许您将DOM元素连接到backend中预定义角色之一(拖动源drag、拖动预览dragPreview或放置目标drop)。

我们的hooks中提供了连接器函数,让我们看看如何使用它来指定放置目标:

<script setup lang="ts">
import { useDrop } from 'vue3-dnd'

const [, drop] = useDrop({})
</script>

<template>
    <div :ref="drop"></div>
</template>

拖拽源(Drag Sources) 和 拖放目标 (Drop Targets)

我们使用拖拽源dragSource来表示拖拽的元素

我们使用拖放目标dropTarget来表示目标接收拖拽元素

使用

开始

在使用Vue3 DnD的时候,我们一般需要使用DndProvider组件,如果没有特殊情况,我们可以将它放在App.vue里边

<script setup lang="ts">
import { DndProvider } from 'vue3-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'
</script>

<template>
  <DndProvider :backend="HTML5Backend">
    <!-- 你的拖拽程序 -->
  </DndProvider>
</template>

拖拽组件

我们可以使用useDrag这个函数,来构建一个拖拽组件。

<script setup lang="ts">
import { useDrag } from 'vue3-dnd'

const [collectedProps, dragSource, dragPreview] = useDrag({
    type: 'BOX',
    item: { id: '1' },
    collect: (monitor) => ({ isDragging: monitor.isDragging() })
})
</script>

<template>
    <div v-if="collectedProps.isDragging" :ref="dragPreview">dragPreview</div>
    <div v-else :ref="dragSource">dragSource</div>
</template>

可以看到,简单的几行代码,我们构建了一个拖拽的元素,它平时展示dragSource,而一旦开始拖拽,它就会展示dragPreview

拖放目标

我们可以使用useDrop这个函数,来构建一个拖放组件。

<script setup lang="ts">
import { useDrop } from 'vue3-dnd'

const [, drop] = useDrop({
    accept: ['BOX']
})
</script>

<template>
  <div :ref="drop">Drop Target</div>
</template>

上边的代码,帮助我们构建了一个拖放组件,它只会对typeBOX的拖拽元素产生反应。

拖动层

我们都知道,在拖拽的过程中,浏览器会给我们提供一个元素的快照,但是我们如果想自己操作这个快照该怎么办呢?这个时候就可以使用useDragLayer这个函数

<script setup lang="ts">
import { useDragLayer } from 'vue3-dnd'

const collectedProps = useDragLayer(monitor => ({ 
      item: monitor.getItem(),
    }))
</script>

<template>
  <div>dragLayer</div>
</template>

上边的例子,就会让你在拖拽的过程中,展示一个dragLayer元素,一般我们会结合useDragdragPreview连接器进行使用。

效果

俗话说的好,有图有真相,没有实际的效果,怎么能知道它的强大呢?

自由拖拽+自定义拖动层

拖拽排序

嵌套的拖拽元素

当然,它还可以实现更多,这里就不再一一展示了。

Vue2

别看它叫vue3-dnd,它同样也可以支持vue2,在vue2中只需要稍微更改一下使用方式即可。

  1. 在vue2中使用,需要先安装@vue/composition-api
  2. 由于Vue2不支持dom ref函数,所以我们必须额外定义一个ref,用于承载dom节点,并将这个ref传递给我们的connect函数。

<template>
    <div
        ref="element"
        role="Box"
        :data-testid="`box-${name}`"
    >
        {{ name }}
    </div>
</template>

<script lang="ts" setup>
import { useDrag } from 'vue3-dnd'
import { ref } from '@vue/composition-api'

interface DropResult {
  name: string
}

const props = defineProps<{ name: string }>()

const [collect, drag, dragPreview] = useDrag(() => ({
    type: 'BOX',
    item: { name: props.name },
}))

const element = ref()
drag(element)
// 可选的,默认与drag一致
dragPreview(element)
// 如果是useDrop,也是一样的
// drop(element)
</script>

结语

为什么不叫vue dnd呢?当然是因为有人已经提前占用了这个包名~

同时我们还希望继续在vue3-dnd的上层提供一些易用性更高的组件,欢迎大家一起参与,敬请期待。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/325906.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

你还没脱单,这些软件都得背锅

不管你是否认可情人节概念&#xff0c;是否会在这天与自己的那个ta相聚&#xff0c;每个成年人都会或多或少地思考自己的感情问题。 在互联网兴盛之前&#xff0c;人与人的交往大都依靠职场关系和熟人介绍来结识新的对象&#xff0c;但也有媒人、婚姻介绍所等专门的职业为适龄…

【Dart】=> [05] Dart初体验-函数

文章目录 函数函数特点可选和默认参数函数对象箭头函数匿名函数综合案例 能够定义并使用Dart函数 学习内容&#xff1a; 函数定义可选和默认参数函数对象箭头函数匿名函数 函数 函数定义 Dart函数的结构&#xff1a; 调用函数&#xff1a; 案例&#xff1a;定义计算任意…

基于Java SSM框架实现学生综合考评管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现学生学生综合考评管理系统演示 摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 学生综合考评管理系统&#xff0c;主要的模块包括查看&#xff1b;管理员&#xff1b;个…

[GXYCTF2019]Ping Ping Ping

1.访问页面&#xff0c;提示传参为ip。2.?ip明显存在命令执行注入&#xff0c;使用 ; 或者 | 闭合上一条命令。 经过fuzz测试&#xff0c;过滤了空格、bash字符、flag字符、以及一些特殊符号。?ip;ls时&#xff0c;发现flag.php就在当前目录下。 3.构造POC&#xff0c;获取…

知识分享:一文读懂AIGC与大模型

什么是大模型&#xff1f; 关于大模型&#xff0c;有学者称之为“大规模预训练模型”(large pretrained language model&#xff09;&#xff0c;也有学者进一步提出”基础模型”(Foundation Models)的概念。 “小模型”&#xff1a;针对特定应用场景需求进行训练&a…

Vue3中使用自定义指令

一&#xff0c;自定义指令&#xff1a; 应用场景&#xff1a;禁用按钮多次点击 1.vue2 a. src/libs/preventClick.js import Vue from vue const preventClick Vue.directive(preventClick, {inserted: function (el, binding) {el.addEventListener(click, () > {if (!el…

05.阿里Java开发手册——前后端规约

【强制】前后端交互的 API&#xff0c;需要明确协议、域名、路径、请求方法、请求内容、状态码、响 应体。 说明&#xff1a; 协议&#xff1a;生产环境必须使用 HTTPS。路径&#xff1a;每一个 API 需对应一个路径&#xff0c;表示 API 具体的请求地址&#xff1a; a&#xff…

【SpringBoot3】Spring Boot 3.0 介绍以及新特性

文章目录 一、Spring Boot 3.01、介绍2、Spring Boot 核心概念3、Spring Boot 3.0 新特性 二、Spring Boot Starter1、介绍2、Starter 命名规则3、官方提供了哪些Starter 三、spring-boot-starter-parent 说明四、示例&#xff1a;创建web项目参考 一、Spring Boot 3.0 1、介绍…

【经典算法】有趣的算法之---遗传算法梳理

every blog every motto: You can do more than you think. 0. 前言 遗传算法是一种基于自然选择和遗传机制的优化算法&#xff0c;因此它通常被用于求解各种最优化问题&#xff0c;例如函数优化、特征选择、图像处理等。 一言以蔽之&#xff1a; 将数学中的优化问题&#xf…

compose部署

目录 本章目标&#xff1a; 自定义网络数据库 正文&#xff1a; 注&#xff1a;创建两个网络mynet和mynetwork 1. 自定义网络-mynet 创建自定义网络&#xff1a; docker network create --subnet172.33.0.0/16 mynet 查看网络信息 docker network list 查看指定网络的详细信…

Leetcode1441.用栈操作构建数组

文章目录 题目原题链接思路代码 题目 给你一个数组 target 和一个整数 n。每次迭代&#xff0c;需要从 list { 1 , 2 , 3 …, n } 中依次读取一个数字。 请使用下述操作来构建目标数组 target &#xff1a; “Push”&#xff1a;从 list 中读取一个新元素&#xff0c; 并将其…

Java中常用的加密算法及其实现原理详解

目录 1、前言 2、对称加密算法 2.1 对称加密算法的工作原理 2.2 DES、AES、RC4算法的原理及其在Java中的实现 2.3 对称加密算法的优缺点 3、非对称加密算法 3.1 非对称加密算法的工作原理 3.2 RSA、DSA算法的原理及其在Java中的实现 3.3 非对称加密算法的优缺点 4、散…

Lamp架构从入门到精通

系列文章目录 lnmp架构 lnmp架构-nginx负载均衡以及高可用 系列文章目录一、源码编译configure(检测预编译环境是否可行)makemake install优化关闭Debug 二、 nginx负载均衡三、nginx的高并发nginx work数量的设定nginx work进程与cpu的静态绑定压力测试nginx高并发修改操作系…

这三款内网管理监控软件让你事半功倍

在当今高度信息化的时代&#xff0c;企业内部网络&#xff08;内网&#xff09;已经成为企业运营和发展的重要支撑。 然而&#xff0c;随着内网规模的扩大和复杂性的增加&#xff0c;内网的管理和监控也变得越来越困难。 为了提高内网的管理效率和工作效率&#xff0c;许多企…

仅用三张图片实现任意场景三维重建:ReconFusion

论文题目&#xff1a; ReconFusion: 3D Reconstruction with Diffusion Priors 论文作者&#xff1a; Rundi Wu, Ben Mildenhall, Philipp Henzler, Keunhong Park, Ruiqi Gao, Daniel Watson, Pratul P. Srinivasan, Dor Verbin, Jonathan T. Barron, Ben Poole, Aleksande…

exFAT文件系统识别不了怎么办?

一般存储驱动器通常会使用几种文件系统&#xff0c;其中比较常见的是FAT32、NTFS和exFAT&#xff0c;那么它们之间有什么区别呢&#xff1f;exFAT文件系统识别不了怎么办&#xff1f; 常用文件系统之间的区别有哪些&#xff1f; FAT32文件系统&#xff1a;它是一个兼容性非常强…

关联系统-智能集成制动系统IPB

整车制动原理 在讲述IPB之前&#xff0c;需要先了解一下整车的制动原理&#xff1a; 如上图所示&#xff1a; 驾驶员踩下制动踏板&#xff0c;由于制动踏板和真空助力器连接&#xff0c;踏板下降的同时会导致真空助力器内压力增大&#xff0c;真空助力器推动制动液进入ESP&am…

九、Qt C++ 数据库开发

《一、QT的前世今生》 《二、QT下载、安装及问题解决(windows系统)》《三、Qt Creator使用》 ​​​ 《四、Qt 的第一个demo-CSDN博客》 《五、带登录窗体的demo》 《六、新建窗体时&#xff0c;几种窗体的区别》 《七、Qt 信号和槽》 《八、Qt C 毕业设计》 《九、Qt …

2024 1.6~1.12 周报

一、上周工作 论文研读 二、本周计划 思考毕业论文要用到的方法或者思想&#xff0c;多查多看积累可取之处。学习ppt和上周组会内容、卷积神经网络。 三、完成情况 1. 数据训练的方式 1.1 迁移学习 迁移学习是一种机器学习方法&#xff0c;把任务 A 训练出的模型作为初始模…

【剑指offer】替换空格

&#x1f451;专栏内容&#xff1a;力扣刷题⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、题目描述1、题目2、示例 二、题目分析1、replaceAll 方法2、StringBuilder3、临时数组 一、题目描述 1、题目 剑指of…