react拖拽排序、js列表拖拽

2023-11-12

列表拖动排序的解决方案有多种,个人感觉最简单的就是zent 提供的 Sortable 组件了

一、zent - Sortable 拖拽排序(推荐、简单明了)

zent 官网 https://zent-contrib.gitee.io/zent/zh/component/sortable
zent githubApi文档 https://zent-contrib.gitee.io/zent/apidoc/

用法:

yarn add zent
# or
npm install zent --save 
import { Sortable, Card } from 'zent';
class Simple extends React.Component {
  state = {
    list: [ {name:'Arvin'},{name:'Jack'},{name: 'Bob'},{name: 'Nick'}]
  }

  // onChane 获取的是排序后的数组
  handleChange = (items) => {
    this.setState({ list: items });
  }

  render() {
    const { list } = this.state;
    return (
      <Sortable
        items={list}
        onChange={this.handleChange}
        // filterClass="stop-to-drag" 不允许拖动的item 类名
      >
        {
          // list.map(({ name } ) => 这里是第一项不允许拖动
          // <Card key={name} className={index?"":"stop-to-drag"}>{name}</Card>)
          list.map(({ name } ) => <Card key={name}>{name}</Card>)
        }
      </Sortable>
    );
  }
}

just so so!!!

二、react-dnd (学习成本很大,不推荐)

官网文档:https://react-dnd.github.io/react-dnd/about

三、纯js手撸

代码地址:https://codepen.io/jhonyoung/pen/PeGpNL?editors=0110

.drag-up {
  animation: dragup ease 0.2s 1;
  animation-fill-mode: forwards;
  border: solid 2px #cccccc;
}

.drag-down {
  animation: dragdown ease 0.2s 1;
  animation-fill-mode: forwards;
  border: solid 2px #cccccc;
}

@keyframes dragup
{
  from { margin-top:10px; }
  to { margin-top:60px; }
}

@keyframes dragdown
{
  from { margin-bottom:10px; margin-top:60px; }
  to { margin-bottom:60px; margin-top:10px; }
}

ul {
  list-style: none
}
class List extends React.Component {
  constructor(props) {
    super(props);
    this.state = {...props};
  }

  dragStart(e) {
    this.dragged = e.currentTarget;
  }
  dragEnd(e) {
    this.dragged.style.display = 'block';

    e.target.classList.remove("drag-up");
    this.over.classList.remove("drag-up");

    e.target.classList.remove("drag-down");
    this.over.classList.remove("drag-down");
    

    var data = this.state.data;
    var from = Number(this.dragged.dataset.id);
    var to = Number(this.over.dataset.id);
    data.splice(to, 0, data.splice(from, 1)[0]);

    //set newIndex to judge direction of drag and drop
    data = data.map((doc, index)=> {
      doc.newIndex = index + 1;
      return doc;
    })

    this.setState({data: data});
  }

  dragOver(e) {
    e.preventDefault();

    this.dragged.style.display = "none";
    
    if (e.target.tagName !== "LI") {
      return;
    }

    //判断当前拖拽target 和 经过的target 的 newIndex

    const dgIndex = JSON.parse(this.dragged.dataset.item).newIndex;
    const taIndex = JSON.parse(e.target.dataset.item).newIndex;
    const animateName = dgIndex > taIndex ? "drag-up" : "drag-down";


    if (this.over && e.target.dataset.item !== this.over.dataset.item) {
      this.over.classList.remove("drag-up", "drag-down");
    }

    if(!e.target.classList.contains(animateName)) {
      e.target.classList.add(animateName);
      this.over = e.target;
    }
  }
  render() {
    var listItems = this.state.data.map((item, i) => {
      return (
        <li 
          data-id={i}
          key={i}
          style={{height: "60px", border: "solid 1px #cccccc", 
          margin: "10px 30%", borderRadius: "5px", backgroundColor: "green", 
          color: "#ffffff"}}
          draggable='true'
          onDragEnd={this.dragEnd.bind(this)}
          onDragStart={this.dragStart.bind(this)}
          data-item={JSON.stringify(item)}
        >{item.color}</li>
      )
     });
    return (
      <ul onDragOver={this.dragOver.bind(this)} className ="contain">
        {listItems}
      </ul>
    )
  }
}
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [
		  { newIndex: 1, color: "red" },
		  { newIndex: 2, color: "green" },
		  { newIndex: 3, color: "blue" },
		  { newIndex: 4, color: "yellow" },
		  { newIndex: 5, color: "orange" },
		  { newIndex: 6, color: "black" }
		]    
    }
  }
  render() {
    return <List data={this.state.data} /> 
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('app'),
);

四、案例三 react Hooks 简写版本

App.js

<Drag 
	data={data} // 必填
	onChange={(newArr:any)=>{
  		console.log(`newArr`, newArr)
	}}
>
{data.map((item,index)=>{
  return <div 
  	key={index} // 使用的key值用来筛选
  	className="drag-item"
  	>
	  {item.color}
	</div>
})}
</Drag>

Drag.js

import React, { useState } from 'react'

interface Dragtype {
  children?:React.ReactElement[],
  onChange:any,
  data: {
    newIndex: number;
    color: string;
  }[]
}

const Drag: React.FC<Dragtype> = (props) =>{
  const [list,setList] = useState<any|React.ReactElement>(props.children)
  const [current,setCurrent] = useState<any>(null)
  const [endIndex,setEndIndex] = useState<any>(null)
  

  const onDragStart = (index:number) => {
    setCurrent(index)
  }

  const onDragEnd = (index:number) =>{
    if(endIndex!==index){
      let _list:any = [...list];
      _list[endIndex] = list[current];
      _list[current] = list[endIndex];
      setList(_list)
      if(props.onChange){
      	// 使用的key值用来筛选
        const newArr = _list.map((i:any)=> props.data[i.key])
        props.onChange(newArr)
      }
    }
    setEndIndex(null)
    setCurrent(null)
  }

  /**
   * @description: 可以获取到当前滑动到第几个
   * @param {any} e 下表数目
   * @param {number} index
   * @return {*}
   */  
  const onDragOver = (index:number) => {
    setEndIndex(index)
  }

  return <div style={{ border:"1px solid red" }}>
    {list.map((item:any,index:any) => <div 
      key={item.key} 
      draggable='true'
      onDragStart={()=>onDragStart(index)}
      onDragOver={()=>onDragOver(index)} // 获取到最终的位置
      onDragEnd={()=>onDragEnd(index)}
    >{item}</div>)}
  </div>;
}
export default Drag;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

react拖拽排序、js列表拖拽 的相关文章

  • GnuWin32的安装与使用

    使用过Linux的伙计估计都会喜欢上linux各种各样强大的命令如 find vim cp mv wget curl grep ls等等 而GnuWin32使windows用户可以在命令行窗口中使用各种各样的linux命令 就跟使用普通的w
  • react新手入门文档

    React React 是什么 React是一个简单的javascript UI库 用于构建高效 快速的用户界面 它是一个轻量级库 因此很受欢迎 它遵循组件设计模式 声明式 编程范式 和 函数式编程 概念 以使前端应用程序更高效 它使用虚拟
  • Vue 打包优化之 生产环境删除 console 日志

    使用 vue cli 3 0 vue cli 脚手架构建的项目 一般在本地开发过程中 会有不少 console 调试信息 如果不处理这些日志信息 默认情况下 即使是构建生产环境的包 这些 console 打印也不会被移除 这显然是不够严谨的
  • 若依RuoYi-Vue代码学习一---通用分页处理

    文章目录 一 先运行看看接口到sql 二 来看看若依怎么处理的分页 三 最后回到接口 及其参数返回 一 先运行看看接口到sql 随便找个表格看看 可以看到传入了 分页关键属性 看看debug的日志打印的sql debug 137 gt Pr
  • Vue 打包优化之 externals 抽离公共的第三方库

    使用 vue cli 脚手架构建的 Vue 全家桶项目 默认配置下 打包后会把 vue vue router axios vuex element ui echarts 等公共库打包在一起 导致基础 chunk vendor 包体积特别大
  • 小程序、微信H5、APP,移动端跨端相互跳转相关规则,2020/11最新总结

    这里只做总结与解释 细则可以去相应官方文档查看 前情提要 其他小程序的appid可以在它的资料里直接查看 所以不是问题 H5 gt 小程序 gt 随便跳 通过微信jssdk openTagList wx open launch weapp
  • 渲染出现的 [Object object] 错误

    可能原因是 String Object导致Object是转换为String 默认结果就成了 Object object 可能的解决方案 在自定义对象定义toString 并返回任何你想要在输出中看到的 使用JSON stringify ob
  • Sass中@each、@for、@if的搭配使用

    CSS 预处理器赋予了 CSS 逻辑编程的能力 其中 Sass Less Stylus 最受欢迎 语法都是大同小异 上手也很快 在项目中使用最多的可能要数 Sass 了 本文就讲讲 Sass 中循环遍历 each for 和 if 判断的搭
  • 前端js调用方法的几种方式

    最近在做前端项目 因为没上vue还是原生的jq方法 所以遇到各种各样的问题 在这记录下几种前端触发的方法 1 onclick 在标签内直接写 nclick qz this 即可 然后js中写方法 2 fxbsbutton click 第一个
  • HTTP协议版本检测

    HTTP 2 0在2015年就已经正式发布了 但是现在大部分网站还在使用HTTP 1 1协议 具体怎么查看网站采用的是HTTP 1 1 还是HTTP 2 0呢 本篇就介绍几种检测HTTP协议版本的方法 所有的操作都是基于Chrome浏览器
  • 学习日志-《掘金/知乎-前端智能化》笔记

    前言 本文记录了学习掘金 知乎 前端智能化过程中的所有笔记 2021前端智能化的总结和展望 https juejin cn post 6966404264633565215 智能化效果图 流程图 前端智能化看 低代码 无代码 https j
  • Vite3 + Svelte3构建Web应用报错:‘process is not defined‘

    Vite爬坑日记 在使用 Vite3 Svelte3 构建 Web 应用时 控制台报错 process is not defined 问题原因 在 Vite 中 process env 全局环境变量被移除了 相当于 process env
  • WIN11如何设置环境变量

    在win11系统中运行环境 比如node js的时候 我们需要进行额外的参数设置 才能继续进行操作 而这个参数设置就是常说的环境变量设置 那么win11系统的环境变量到底怎么进行配置呢 1 键盘输入 win R 打开运行框 2 输入命令 c
  • 浏览器滚动到底部页面加载问题

    问题描述 页面在m端展示的时候 滚动到底部应该自动加载下一页 但是却没有 解决办法 在有些浏览器滚动下滚动时 滚动到底部仍然不会触发一般的底部加载事件的条件 可以在距离底部有一定距离时进行滚动加载事件的触发 if windowHeight
  • # vue# 【九】 个人中心的制作

    Z vue个人中心的制作 个人中心的制作 在实际开发里面 经常会有一些登录页需要进行编写 例如下面这些类型 而这些版面的制作 比较讲究的是思路问题 例如我们想要制作一个登录页 点击就可以输入名字 并且修改名字 整体思路 我们可以先把整体拆分
  • 阻止移动端 touchmove 与 scroll 事件冲突

    在移动端开发过程中 如果要实现一个元素或按钮的拖动定位 会出现很多坑 例如 元素上下移动过程中 会触发 body 的 scroll 事件 导致整体的位置偏移 这时就需要 阻止移动端 touchmove 与 scroll 事件冲突 一 解决思
  • Shell 中常用 Date 日期的计算

    在使用 Crontab 定时任务和 Shell 脚本切割 Nginx 日志文件时 要用到时间戳 当月 上月 下月 上月初 上月末 下月初 下月末等等 其中有些日期不能直接获取 需要经过一定的计算才能得到 一 Date 基础格式化 格式 输出
  • Tauri 应用中发送 http 请求

    最近基于 Tauri 和 React 开发一个用于 http https 接口测试的工具 Get Tools 其中使用了 tauri 提供的 fetch API 在开发调试过程中遇到了一些权限和参数问题 在此记录下来 权限配置 在 taur
  • setTimeout引发的刨根问底

    setTimeout 定时器 是JavaScript中一个比较重要且常用的方法 该方法用于在指定的毫秒数后调用函数或计算表达式 平时开发可能基本都是使用 setTimeout fn ms 的形式 当然还有比较神奇的用法 特别是在前端面试中
  • React Native

    小手动一动 点赞转发加关注 微信搜索 大前端杂货铺 公众号关注大前端老司机带您遨游大前端知识的海洋 关注 Github https github com big frontend 还有大前端代码实践哦 java 与 javascript 互

随机推荐

  • 一款做思维导图的神奇软件——MindMaster

    文章目录 1 思维导图的作用 2 如何下载MindMaster 3 如何使用MindMaster 3 1新建模板 3 2选择主题格式和页面格式 4 总结 1 思维导图的作用 从思维模式来开 思维导图是一种高效的模式 它主要是使用图文并茂的方
  • 软件开发的各步骤以及需要的工具

    1 需求调研 MindMap 工具使用FreeMind或MindManager 2 架构设计 UML ER 工具 PowerDesigner Togather RationalRose 3 数据库设计 PowerDesigner SQL20
  • Apple 允许您指定在您死后谁可以访问您的账户

    在周一的WWDC 2021活动中 Apple 宣布 从今年秋季的 iOS 15 和 macOS Monterey 操作系统更新开始 将可以指定在您死亡的情况下谁可以访问您的账户 新功能称为数字遗产 它使亲戚或朋友更容易访问已故亲人拥有的数码
  • ZYNQ7000系列 DDR读取正确性

    摘要 使用ZYNQ或者MPSoC的好处是可以通过PL逻辑设计硬件加速器 对功能进行硬件加速 加速器和ARM之间的交互信息一般包含自定义加速指令传递 待计算数据以及计算结果 这三种交互信息 使用ZYNQ或者MPSoC的好处是可以通过PL逻辑设
  • java 档案整理 生成归档章 透明背景图片

    import javax imageio ImageIO import java awt import java awt image BufferedImage import java io File import java io IOEx
  • unity3d鼠标点击,获取世界坐标

    unity中有关于鼠标位置的函数 Input mousePosition 但不得不说 这个函数不到位 可以用一个print函数输出一下这个坐标会发现 只有X Y值在改变 Z值没有发生变化 并且在屏幕的左下角固定为 0 0 0 查看文档后发现
  • 类加载器是否为空

    package com bzu csh 项目名称 Test1 类名称 Test2 类描述 创建人 admin 创建时间 2017年1月7日 下午9 41 36 修改人 admin 修改时间 2017年1月7日 下午9 41 36 修改备注
  • 数据可视化之折线图绘制

    使用python中的matplotlib绘制折线图 环境需求 python 或者anaconda pycharm 和第三方库matplotlib 首次先绘制简单的折线图 其他的参数可以在使用熟练后一点一点的加入 import matplot
  • 计算机网络课程笔记

    学习MOOC华南理工计算机网络课程笔记 第1章 概述 1 1 为什么要学习计算机网络 1 2 互联网发展史 1 3 常用的基本概念 1 4 参考模型 1 5 参考模型相关概念 1 6 本课程的组织 第2章 物理层 2 1 物理层概述 2 2
  • JNI编程—JNI基础

    什么是JNI 怎么使用 JNI Java Native Interface 它是Java平台的一个特性 并不是Android系统特有的 其实主要是定义了一些JNI函数 让开发者可以通过调用这些函数实现Java代码调用C C 的代码 C C
  • python 如何编写一个自己的包

    python 如何编写一个自己的包 先写function 内容 package wadepypk ls init py f1 py f2 py f1 py def show print in pkg f show f2 py def sho
  • unix bsd linux gun   粗略解释

    最早的unix是开放的 很多组织对unix都有修改 期中比较有名的就是伯克利大学的修改版本 叫做bsd 是unix的分支 由于bsd的协议允许你直接使用 修改他的代码 并且可以作为商业用途 所以很多公司的unix都是从bsd衍生过来的 比如
  • mongodb学习笔记一:mongodb安装与介绍

    一 前言 最近开始学习非关系型数据库MongoDB 却在博客园上找不到比较系统的教程 很多资料都要去查阅英文网站 效率比较低下 本人不才 借着自学的机会把心得体会都记录下来 方便感兴趣的童鞋分享讨论 部分资源出自其他博客 旨将零散知识点集中
  • C/C++函数模板template

    1 说明 当函数处理功能相似 函数名相同 但是参数个数或者类型有区别 我们知道实现的方式是依靠函数重载 overload 但是如果仅函数参数或返回数的类型不同 我们想到靠函数模板解决这个问题 不仅节省内存 而且不用复杂声明多个函数 函数模板
  • 为线程池中的每个线程设置UncaughtExceptionHandler

    参考了 java并发编程实战 P134内容 每当线程池需要创建一个线程时 都是通过调用线程工厂方法来完成的 默认的线程工厂方法将创建一个新的 非守护的线程 并且不包好特殊的配置信息 如果你希望在线程运行之前 之后 或者运行中如果发生异常等情
  • Linux 系统 lscpu 命令详解

    文章目录 前言 lscpu 命令详解 命令 1 查看物理 CPU 个数 2 查看每个物理 CPU 核数 3 查看总线程数 4 查看内存信息 5 查看 linux 系统版本 前言 Linux 系统查看系统相关信息方法很多 以下详细介绍 lsc
  • 一颗二叉树代码(图解)

    什么是二叉树 树结构是一种非线性存储结构 存储的是具有一对多关系的数据的集合 而树形结构的一种抽象出来的数据结构往往是二叉树的形式 满足以下两个条件的树就是二叉树 本身是有序树 树中包含的各个节点的度不能超过 2即只能是 0或者1 或者 2
  • 项目时间管理-架构真题(二十四)

    1 霍尔提出了系统方法的三维结构体系 通常称为霍尔三维结构 这就是系统工程方法论的基础 霍尔三维结构以时间堆 堆 知识堆组成的立体结构概括性表示出系统工程在各阶段 各步骤以及所涉及的知识范围 其中时间维是系统的工作进程 对于一个具体的工程项
  • 计算机网络面试八股文攻略(二)—— TCP 与 UDP

    一 基础概念 TCP 与 UDP 是活跃于 运输层 的数据传输协议 TCP 传输控制协议 Transmission Control Protocol 提供面向连接的 可靠的数据传输服务 具体来说就是一种要建立双端连接才能发送数据 能确保传输
  • react拖拽排序、js列表拖拽

    列表拖动排序的解决方案有多种 个人感觉最简单的就是zent 提供的 Sortable 组件了 一 zent Sortable 拖拽排序 推荐 简单明了 zent 官网 https zent contrib gitee io zent zh