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列表拖拽 的相关文章

  • SolidJS——前端新秀框架,性能直逼原生JS

    SolidJS 是什么 SolidJS是一个声明式 高效且灵活用于构建用户界面的 JavaScript 库 Solid 号称拥有 JSX 语法 类似于 React hook 的语法 你可以用现代化的开发方式 获得性能最快的代码 一 性能比较
  • Vue 打包优化之 externals 抽离公共的第三方库

    使用 vue cli 脚手架构建的 Vue 全家桶项目 默认配置下 打包后会把 vue vue router axios vuex element ui echarts 等公共库打包在一起 导致基础 chunk vendor 包体积特别大
  • Webpack详解

    零 文章目录 Webpack详解 1 webpack基本概念 1 webpack是什么 静态模块打包工具 官网 https webpack docschina org 官网文档 https webpack docschina org con
  • 在ElementUI的$notify通知方法中渲染自定义组件

    ElementUI 的 Notification 组件通常用于全局的通知提醒消息 其中展示内容默认是文本字符串 当然也可以设置 dangerouslyUseHTMLString true 后传入 HTML 片段 如果要展示比较复杂的动态内容
  • 多版本node的安装和巧妙切换

    1 安装多版本node的原因 在项目开发过程中 不同项目使用的 node版本不同 有时会因为node版本过高或太低 导致报错 本文将教你如何在同一个系统中安装多个版本的node并且快速而且 巧妙地切换 2 安装指定版本的node 点击进入
  • HTML特殊字符符号大全

    HTML常用特殊字符 只要你认识了 HTML 标记 你便会知道特殊字符的用处 HTML 原代码 显示结果 描述 lt lt 小于号或显示标记 gt gt 大于号或显示标记 amp 可用于显示其它特殊字符 quot 引号 reg 已注册 co
  • React中 useState在合成事件中是异步的,怎么获取到useState 设置后的最新值,或者说setState中获取到最新值

    useState 在合成事件中是异步的 合成时间是什么呢 合成事件 简单来说 比如onClick 或者 onChange 或者说是 Input之类的事件 所以一个情景是这样的 当你在onClick 中这样设置了状态 并赋值上去 但是打印的值
  • flutter图片显示

    图片显示 本地图片显示 首先项目根目录下创建一个用于放置图片的文件夹 将要显示的图片放进去 如下图 然后在项目根目录的pubspec yaml文件中的assets下添加图片路径 如下图 在需要显示图片的地方使用Image asset 进行加
  • 前端js调用方法的几种方式

    最近在做前端项目 因为没上vue还是原生的jq方法 所以遇到各种各样的问题 在这记录下几种前端触发的方法 1 onclick 在标签内直接写 nclick qz this 即可 然后js中写方法 2 fxbsbutton click 第一个
  • 学习日志-《掘金/知乎-前端智能化》笔记

    前言 本文记录了学习掘金 知乎 前端智能化过程中的所有笔记 2021前端智能化的总结和展望 https juejin cn post 6966404264633565215 智能化效果图 流程图 前端智能化看 低代码 无代码 https j
  • Svelte 实现 keypress 快捷键功能

    有些框架中内置了常用的事件修饰符和按键修饰符 例如 Vue 中就提供了按键 enter 13 修饰键 ctrl alt shift meta等修饰符 简化了很多快捷键功能的实现 在 Svelte 中也提供了 preventDefault s
  • HTML 表单标签

    一 什么是表单标签 表单是用来采集用户的输入数据 然后将数据提交给服务器 二 表单的组成 一个表单有三个基本组成部分 表单标签 这里面包含了处理表单数据所用程序的URL以及数据提交到服务器的方法 表单域 包含了文本框 密码框 隐藏域 多行文
  • Blob 文件下载对应的常见 MIME 类型列表

    Blob 对象表示一个不可变 原始数据的类文件对象 它的数据可以按文本或二进制的格式进行读取 也可以转换成 ReadableStream 来用于数据操作 在 JS 中通常使用 Blob 进行文件下载保存 new 转换过程中需要指定下载文件
  • # vue# 【九】 个人中心的制作

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

    在移动端开发过程中 如果要实现一个元素或按钮的拖动定位 会出现很多坑 例如 元素上下移动过程中 会触发 body 的 scroll 事件 导致整体的位置偏移 这时就需要 阻止移动端 touchmove 与 scroll 事件冲突 一 解决思
  • 再读红宝书(第四版) 第五章 基本引用类型

    引用值 或者对象 是某个特定引用类型的实例 在 ECMAScript 中 引用类型是把数据和功能组织到一起的结构 经常被人错误地称作 类 虽然从技术上讲 JavaScript 是一门面向对象语言 但ECMAScript 缺少传统的面向对象编
  • Tauri 应用中发送 http 请求

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

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

    近年来 前端技术日新月异 Vite Vue3 Svelte SolidJS 等框架工具大放异彩 身为一个前端开发 总感觉一刻不学习就要out了 最近使用 Vite3 Svelte3 来构建封装自定义的 Web Components 开始了艰
  • vue——vue-video-player插件实现rtmp直播流

    更新 flash已不可再使用 大家另寻出路吧 安装前首先需要注意几个点 vue video player插件 其实就是 video js 集成到 vue 中 所以千万不要再安装 video js 可能会出错 视频流我这个项目选择rtmp格式

随机推荐

  • 一款做思维导图的神奇软件——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