react 基于 dnd-kit 封装的拖拽排序组件

这篇具有很好参考价值的文章主要介绍了react 基于 dnd-kit 封装的拖拽排序组件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

dnd-kit使用方法

  • 官网地址 https://docs.dndkit.com/introduction/installation

  • 安装依赖

npm install @dnd-kit/core
npm install @dnd-kit/sortable
  • 简单使用

建议直接看官网,已经描述得很详细了:https://docs.dndkit.com/presets/sortable文章来源地址https://www.toymoban.com/news/detail-598712.html

封装成组件使用

效果展示
dnd-kit,component,react.js,javascript,前端
type dataType = {
  id: string
  title: string
}
export default () => {
  const [list, setList] = useState<dataType[]>([])
  useEffect(() => {
    getData()
  }, [])

  const getData = async () => {
    setTimeout(() => {
      const data = new Array(10).fill('标题-').map((s,i) => (
        {id: 'id-' + i, title: s + i}
      ))
      setList(data)
    }, 200);
  }

  const onDragEnd = (list: dataType[], ids: string[]) => {
    setList(list)
  }

  return (
    <div >
      <SortListDndKit list={list} onDragEnd={onDragEnd}>
        {list.map((item) => (
          <SortItemDndKit key={item.id} id={item.id}>
            <div>
              <h4>{item.title}</h4>
            </div>
          </SortItemDndKit>
        ))}
      </SortListDndKit>
    </div>
  )
}
注意事项
  1. 如果传入的是一个函数式组件,需要用一个html元素包裹住
<SortListDndKit list={list} onDragEnd={onDragEnd}>
{list.map((item) => (
  <SortItemDndKit>
    {/* 这里需要用html元素包裹一下 */}
    <div>
      <Text title='测试组件' />
    </div>
  </SortItemDndKit> 
))}
</SortListDndKit>
  1. 这里的排序默认是读取 list 中的 id 作为 key 值的,如果 key 值是其他,可以指定 list 中传入的 idKey
{/* newId:list中的id名称 */}
<SortListDndKit idKey="newId" list={list} onDragEnd={onDragEnd}></SortListDndKit>
  1. 如果内部的元素绑定了鼠标点击之类的事件,需要先阻止事件冒泡 onMouseDown={e => e.stopPropagation()}
<SortListDndKit list={list} onDragEnd={onDragEnd}>
{list.map((item) => (
  <SortItemDndKit>
    {/* 这里需要用html元素包裹一下 */}
    <div>
      <h4>这里有很多内容</h4>
      {/* 这里需要阻止鼠标点击事件的冒泡 */}
      <button onMouseDown={e => e.stopPropagation()} onClick={()=>console.log('点击了')} >点击</button>
    </div>
  </SortItemDndKit> 
))}
</SortListDndKit>
组件源码
import React, { ReactNode } from 'react';
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragEndEvent,
  MouseSensor,
} from '@dnd-kit/core';
import {
  arrayMove,
  SortableContext,
  sortableKeyboardCoordinates,
  useSortable,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

type PropsType = {
  /** 需要传递的列表 */
  list: any[];
  /** list的key值,默认是id */
  idKey?: string;
  children: ReactNode;
  /** 拖拽结束的回调 */
  onDragEnd: (arr: any[], ids: string[]) => void;
};

/** 参考官网:https://docs.dndkit.com/presets/sortable */
/** 
 * 列表排序
 */
export const SortListDndKit = ({
  list = [],
  idKey = 'id',
  children,
  onDragEnd,
}: PropsType) => {
  // 指定传感器,默认是全部
  const sensors = useSensors(
    // useSensor(PointerSensor),
    useSensor(MouseSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    }),
  );
  // 拖拽结束
  const handleDragEnd = (event: DragEndEvent) => {
    const { active, over } = event;
    if (active.id !== over.id) {
      const oldIndex = list.findIndex((item) => item[idKey] === active.id);
      const newIndex = list.findIndex((item) => item[idKey] === over.id);
      const ids: string[] = list.map((item) => item[idKey]);
      [ids[newIndex], ids[oldIndex]] = [ids[oldIndex], ids[newIndex]];
      const _val = arrayMove(list, oldIndex, newIndex);
      onDragEnd(_val, ids);
    }
  };

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <SortableContext items={list.map((item) => item[idKey])}>
        {children}
      </SortableContext>
    </DndContext>
  );
};

type SortItemType = {
  id: string;
  children: ReactNode;
};

/**
 * 列表排序的子项
 * - 函数式组件作为children,需要用html元素包裹住
 * - 例:
 * - \<SortItemDndKit>
 * -   \<div>\<Text title='测试组件' />\</div>
 * - \</SortItemDndKit> 
 */
export const SortItemDndKit = ({ id, children }: SortItemType) => {
  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id });
  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
  };
  const newChild = React.Children.map(children, (child) => {
    if (!React.isValidElement(child)) {
      return null;
    }
    const childProps = {
      ...child.props,
      ref: setNodeRef,
      style,
      ...attributes,
      ...listeners,
    };
    return React.cloneElement(child, childProps);
  });
  return <>{newChild}</>;
};

到了这里,关于react 基于 dnd-kit 封装的拖拽排序组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于vue element-ui 封装上传图片组件 功能:上传,删除,预览,上传图片水印,拖拽排序,上传进度条等

    我们在开发后台时肯定避免不了上传图片的功能 例如: 上传图片回显 上传完成 : 预览查看 , 删除等 如果是图片列表,还可能让你拖动图片排序 有的后台项目可能要给图片添加水印,添加标记 有的后台可能要炫酷一点 添加进度条功能 现在我们要完成上面的一系列功能,这里我

    2024年02月16日
    浏览(47)
  • [开源]基于Vue的拖拽式数据报表设计器,为简化开发提高效率而生

    Cola-Designer 是一个 基于VUE,实现拖拽 + 配置方式生成数据大屏,为简化开发、提高效率而生。 使用GPL-2.0开源协议 部分截图:     实现完全拖拽 + 配置式生成大屏,设计即生产。(动态数据需要后端提供API接口) 项目采用行业流行架构:SpringBoot+Vue,开发部署方便。 内置

    2024年02月06日
    浏览(30)
  • 小程序封装拖拽菜单组件(uniapp拖拽排序,自定义菜单)

    使用movable-area作为可移动区域,并在内部循环渲染列表项view,绑定touch事件。 在mounted生命周期函数内获取区域movable-area的dom信息,记录列表项的坐标信息。 在methods中定义了列表项的touchstart、touchmove和touchend事件的方法,用于实现列表项的拖拽移动和位置变更。 watch监听列表项数

    2023年04月20日
    浏览(24)
  • 封装React组件DragLine,鼠标拖拽的边框改变元素宽度

    原文合集地址如下,有需要的朋友可以关注 本文地址 合集地址 在项目中,设计说想做个面板,其宽度随鼠标拖拽而变化,有最大最小值。基于这个小功能封装一个可拖拽组件,在需要的地方引入即可。 这里只是实现x方向的拖拽,y轴拖拽思路差不多。 既然是鼠标操作,那肯

    2024年02月16日
    浏览(30)
  • 简单使用vue拖拽组件vue3-dnd

    项目中需要使用到拖拽,这里使用vue3-dnd来满足需求 这里项目使用的vue3(使用js而非ts) 插件官网地址:Vue3 DnD 安装 然后在app.vue里面添加代码  通过DndProvider组件为项目提供拖拽功能  概念 项目item和类型:被拖拽的对象我们称呼为某种类型的项目,类型的作用是让放置目标

    2023年04月13日
    浏览(33)
  • vue3自定义拖拽,vue3-dnd 的使用

    资料地址: 入门文档:https://hcg1023.github.io/vue3-dnd/guide/ 案例文档:https://hcg1023.github.io/vue3-dnd/example/ react-dnd:https://react-dnd.github.io/react-dnd/docs/overview 踩坑记录: 1、安装时需要安装react-dnd-html5-backend npm install vue3-dnd react-dnd-html5-backend 2、标签要包裹在app外层,而不是放在你想要

    2024年02月09日
    浏览(28)
  • HTML5新增的拖拽属性draggable,怎么实现拖拽?

    1、draggable 属性规定元素是否可拖动。 2、提示: 链接和图像默认是可拖动的。 3、提示: draggable 属性经常用于拖放操作。 注意:draggable 属性是 HTML5 新增的。 设置属性值 值 描述 true 规定元素是可拖动的。 false 规定元素是不可拖动的。 auto 使用浏览器的默认特性。 代码演

    2024年02月16日
    浏览(30)
  • vue的拖拽插件: vue.draggable

    中文文档地址: vue.draggable中文文档 - itxst.com Vue.Draggable是一款基于Sortable.js实现的vue拖拽插件。支持移动设备、拖拽和选择文本、智能滚动,可以在不同列表间拖拽、不依赖jQuery为基础、vue 2过渡动画兼容、支持撤销操作,总之是一款非常优秀的vue拖拽组件。 https://www.itxst.co

    2024年02月14日
    浏览(31)
  • 原生JS的拖拽属性draggable(详解)

    摘要 作为h5新增的属性draggable,它能够给与一切的html元素拖动的效果。而在这个属性之下,也有着关于拖动效果的各个方法。 而这一篇文章,主要就是说一下关于draggable属性的使用以及工作场景。 1.了解draggable属性的使用 对我来讲,我希望在学习一个知识的时候,最开始就

    2023年04月19日
    浏览(29)
  • react-dnd的使用

    React DnD(Drag and Drop)是一个用于实现拖放功能的 React 拓展库。它提供了一组用于构建可拖动和可放置组件的高阶组件和钩子函数。 安装  react-dnd  和  react-dnd-html5-backend : 创建一个拖放容器组件和一个可拖动的组件。 拖放容器组件(DragDropContainer)负责管理拖放行为,并提

    2024年02月13日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包