React.js组件实现拖拽排序组件功能过程解析

因为使用了react.js技术栈,所以封装优先考虑输入和输出。基于数据驱动去渲染页面、控制拖拽元素的顺序。

由于我不考虑兼容IE8等旧版本浏览器,拖拽的效果采用了HTML5的拖放(Drag 和 drop)。当然,如果要求兼容性丰富,使用鼠标点击的相关事件也很简单。

实现的效果如下:

第一步是先了解H5拖放的相关属性,MDN上有详细的说明,链接

有一点需要注意的是,react.js会给所有的属性事件名称前加上"on",后面则为驼峰式写法。例如原生的click事件,在react.js里应使用onClick事件。

我的组件使用的拖放属性如下:

  • draggable 当设置为true时,当前控件可以拖拽
  • onDragStart 控件开始被拖拽时触发的事件,它提供一个dataTransfer.setData()方法,将必要的数据存储在对象中便于在其它方法中调用
  • onDragOver 规定当前控件可以接收拖拽的组件的方法,一般在此方法中阻止冒泡
  • onDragEnter 拖动后鼠标进入另一个可接受区域时触发,通过它可以实现移入效果
  • onDragLeave a拖到b,离开b的时候触发,可以用于监听消除移入效果的时机
  • onDrop 当控件被“释放”到一个有效的释放目标位置时触发,我在这个方法中处理数据,并通过它调用onChange方法,将value值暴露给父组件

其中draggable,onDragStart是被“拖拽”方需要设置的属性,onDragOver,onDragEnter,onDragLeave和onDrop是被“拖入”方需要设置的属性。不过对于我的拖拽排序组件,每一个元素都是拖拽和拖入方

第二步,既然“她"是react.js的组件, 按照习惯,简单的将输入属性定为为value,同时,暴露onChange事件监听value的变化,并将其暴露给父组件,同时,暴露一个属性sortKey告诉组件使用哪个key作为排序字段。
既然涉及到排序,同时允许指定组件每个元素的内部子组件,我将输入数据格式定义为一个数组对象,其中content可以为reactNode:

 value: [
    {
     content: 'div1',
     code: '01',
     sort: 0,
    },
    {
     content: 'div2',
     code: '02',
     sort: 1
    },
    {
     content: 'div3',
     code: '03',
     sort: 2
    },
    {
     content: 'div5',
     code: '05',
     sort: 5
    },
    {
     content: 'div4',
     code: '04',
     sort: 4
    }]

根据value我去生成可排序组件的每个node,关键代码如下:

 // 生成拖拽组件
 createDraggleComponent(data, sortKey, style, uId) {
  return data.sort(this.compare(sortKey)).map((item) => {
   return (
    <div
     className={styles.content}
     key={item.code}
     draggable={true}
     onDragEnter={this.dragenter.bind(this)}
     onDragLeave={this.dragleave.bind(this)}
     onDragStart={this.domdrugstart.bind(this, item[sortKey], item.code, uId, item)}
     onDrop={this.drop.bind(this, item[sortKey], data, sortKey, uId)}
     onDragOver={this.allowDrop.bind(this)}
     style={{ ...style }}>{item.content}</div>
   )
  })
 }
 render() {
  const { value, sortKey, style } = this.props;
  return (
   <Row>
    <div style={{ display: 'flex', flexDirection: 'row' }}>
     {this.createDraggleComponent(value, sortKey, style)}
    </div>
   </Row>
  )
 }

其中的属性方法具体实现:

 // 拖动事件
 domdrugstart(sort, code, ee) {
  ee.dataTransfer.setData("code", code);
  ee.dataTransfer.setData("sort", sort);
 }
 // 拖动后鼠标进入另一个可接受区域
 dragenter(ee) {
  ee.target.style.border = '2px dashed #008dff';
  ee.target.style.boxShadow = '0 0 8px rgba(30, 144, 255, 0.8)';
 }
 // a拖到b,离开b的时候触发
 dragleave(ee) {
  ee.target.style.border = '1px solid grey';
  ee.target.style.boxShadow = '';
 }
 // 对象排序
 compare(key) {
  return (obj1, obj2) => {
   if (obj1[key] < obj2[key]) {
    return -1;
   } else if (obj1[key] > obj2[key]) {
    return 1;
   }
   return 0
  }
 }
 // 当一个元素或是选中的文字被拖拽释放到一个有效的释放目标位置时
 drop(dropedSort, data, sortKey, ee) {
  ee.preventDefault();
  const code = ee.dataTransfer.getData("code");
  const sort = ee.dataTransfer.getData("sort");
  if (sort < dropedSort) {
   data.map(item => {
    if (item.code === code) {
     item[sortKey] = dropedSort;
    } else if (item[sortKey] > sort && item[sortKey] < dropedSort + 1) {
     item[sortKey]--;
    }
    return item;
   });
  } else {
   data.map(item => {
    if (item.code === code) {
     item[sortKey] = dropedSort;
    } else if (item[sortKey] > dropedSort - 1 && item[sortKey] < sort) {
     item[sortKey]++;
    }
    return item;
   });
  }
  this.props.onChange(data)
 }
 allowDrop(ee) {
  ee.preventDefault();
 }

值得注意的点其实只有一个,我控制顺序的时候,并没有使用.target.before(document.getElementById({id}))去实际操控节点,而是在每次触发onDrop时间的时候,处理数据的sort,并通过onChange事件暴露给父组件,将数据输出,通过改变value值触发虚拟dom重新去渲染,以此控制顺序。

根据公司的要求,在此基础上,我还实现了拖拽复制的功能,这个等下次自己不懒的时候再记录下来。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 老生常谈js-react组件生命周期

    组件的生命周期可分成三个状态: •Mounting:已插入真实 DOM •Updating:正在被重新渲染 •Unmounting:已移出真实 DOM 生命周期的方法有: •componentWillMount 在渲染前调用,在客户端也在服务端. •componentDidMount : 在第一次渲染后调用,只在客户端.之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问. 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeou

  • react组件基本用法示例小结

    本文实例讲述了react组件基本用法.分享给大家供大家参考,具体如下: 组件间传值: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <div id="app"> </div> &l

  • 浅谈React Native 中组件的生命周期

    概述 就像 Android 开发中的 View 一样,React Native(RN) 中的组件也有生命周期(Lifecycle).所谓生命周期,就是一个对象从开始生成到最后消亡所经历的状态,理解生命周期,是合理开发的关键.RN 组件的生命周期整理如下图: 如图,可以把组件生命周期大致分为三个阶段: 第一阶段:是组件第一次绘制阶段,如图中的上面虚线框内,在这里完成了组件的加载和初始化: 第二阶段:是组件在运行和交互阶段,如图中左下角虚线框,这个阶段组件可以处理用户交互,或者接收事件更新界面: 第

  • React组件生命周期详解

    调用流程可以参看上图. React组件提供了生命周期的钩子函数去响应组件不同时刻的状态,组件的生命周期如下: 实例化 存在期 销毁期 实例化 首次调用组件时,有以下方法会被调用(注意顺序,从上到下先后执行): getDefaultProps 这个方法是用来设置组件默认的props,组件生命周期只会调用一次.但是只适合react.createClass直接创建的组件,使用ES6/ES7创建的这个方法不可使用,ES6/ES7可以使用下面方式: //es7 class Component { stat

  • react基本安装与测试示例

    本文实例讲述了react基本安装与测试.分享给大家供大家参考,具体如下: 语法特点: 声明式编码:只在意结果不在意过程 组件化编码:html,css,js的集合 单向数据流:vue也是单向数据流,有一个双向绑定功能. 支持服务器端编写 高效:先生成一个虚拟DOM,然后在DOM中操作,再一次性返回到真实界面 首先安装好node.js和npm 安装 Webpack:npm install -g webpack 安装对应的 loader: npm install babel-loader --save

  • React生命周期原理与用法踩坑笔记

    本文实例讲述了React生命周期原理与用法.分享给大家供大家参考,具体如下: React生命周期 生命周期概览 生命周期的状态 组件的生命周期可分成三个状态: Mounting:已插入真实 DOM Updating:正在被重新渲 Unmounting:已移出真实 DOM componentWillMount 在渲染前调用,在客户端也在服务端. 生命周期介绍 componentDidMount : 在第一次渲染后调用,只在客户端.之后组件已经生成了对应的DOM结构,可以通过this.getDOMN

  • vue生命周期和react生命周期对比【推荐】

    个人认为,react和vue的业务逻辑是差不多,vue在react上封装了更简洁的方法,使用起来更加的便捷,如:提供了便捷的指令(v-for,v-if,v-model),还提供了更多的属性(computed,watch),我还是比较喜欢用react的,更接近js原生,更容易于理解它. 一 vue的生命周期如下图所示(很清晰)初始化.编译.更新.销毁 二 vue生命周期的栗子 注意触发vue的created事件以后,this便指向vue实例,这点很重要 <!DOCTYPE html> <h

  • react PropTypes校验传递的值操作示例

    本文实例讲述了react PropTypes校验传递的值操作.分享给大家供大家参考,具体如下: 校验传递的值: import React, { Component, Fragment } from 'react'; import List from './List.js'; class Test extends Component { constructor(props) { super(props); this.state={ inputValue:'aaa', list:['睡觉','打游戏

  • React中Ref 的使用方法详解

    本文实例讲述了React中Ref 的使用方法.分享给大家供大家参考,具体如下: React中Ref 的使用 React v16.6.3 在典型的React数据流中,props是父组件与其子组件交互的唯一方式.要修改子项,请使用new props 重新呈现它.但是,在某些情况下,需要在典型数据流之外强制修改子项.要修改的子项可以是React组件的实例,也可以是DOM元素.对于这两种情况,React都提供了api. 何时使用refs refs有一些很好的用例: 1.文本选择或媒体播放. 2.触发势在

  • React.js组件实现拖拽排序组件功能过程解析

    因为使用了react.js技术栈,所以封装优先考虑输入和输出.基于数据驱动去渲染页面.控制拖拽元素的顺序. 由于我不考虑兼容IE8等旧版本浏览器,拖拽的效果采用了HTML5的拖放(Drag 和 drop).当然,如果要求兼容性丰富,使用鼠标点击的相关事件也很简单. 实现的效果如下: 第一步是先了解H5拖放的相关属性,MDN上有详细的说明,链接 有一点需要注意的是,react.js会给所有的属性事件名称前加上"on",后面则为驼峰式写法.例如原生的click事件,在react.js里应使

  • react 实现表格列表拖拽排序的示例

    目录 问题描述 思路 解析 1. react-sortable-hoc 2. array-move 问题描述 在项目开发中,遇到这样一个需求:需要对表格里面的数据进行拖拽排序. 效果图如下所示: 思路 安装两个插件: react-sortable-hoc (或者 react-beautiful-dnd) array-move npm install --save react-sortable-hoc npm install --save array-move 解析 1. react-sortab

  • vue实现列表拖拽排序的功能

    在日常开发中,特别是管理端,经常会遇到要实现拖拽排序的效果:这里提供一种简单的实现方案. 此例子基于vuecli3 首先,我们先了解一下js原生拖动事件: 在拖动目标上触发事件 (源元素): ondragstart - 用户开始拖动元素时触发 ondrag - 元素正在拖动时触发 ondragend - 用户完成元素拖动后触发 释放目标时触发的事件: ondragenter - 当被鼠标拖动的对象进入其容器范围内时触发此事件 ondragover - 当某被拖动的对象在另一对象容器范围内拖动时触

  • js实现横向拖拽导航条功能

    效果如下: 代码如下: <!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>div横向拖拽排序</title> <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script> <style type="text/cs

  • js实现鼠标拖拽多选功能示例

    最近做了一个用js实现鼠标拖拽多选的功能,于是整理了一下思路,写了一个小demo: 遮罩出现: 被遮罩盖住的,即为选中的块(背景色为粉色) 下面是具体代码,注释已在文中,与大家交流. <!DOCTYPE html> <html> <head> <title>鼠标拖拽多选功能</title> <script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"&

  • Vue拖拽排序组件Vue-Slicksort解读

    目录 一.效果图 二.安装组件 三.使用组件 四.组件参数 五.组件方法 HandleDirective 总结 一.效果图 二.安装组件 npm i vue-slicksort -S 三.使用组件 <div class="maintenance_img mt50 mb50 pl20 pr20" style="font-size: 16px;font-weight: 600;position: relative;"> <!-- 拖拽 --> &

  • react.js组件实现拖拽复制和可排序的示例代码

    在实现复制前,对之前的拖拽排序组件属性进行了修改. 摒弃了value中的content属性,拖拽组件暴露的render函数,利用这个属性进行组件内部子组件的渲染,这点主要是参考了蚂蚁金服的Ant design里面一些组件的设计. 为了实现Data和model的脱藕,和sortKey一样,组件增加codeKey属性. 拖拽复制的效果如下: 由于实现组件的核心是根据value数据来渲染页面,因此实现拖拽复制功能,只需要在"拖拽释放"的时候,将被拖拽方的数据放到当前目标所在的value数组中

  • Elementui表格组件+sortablejs实现行拖拽排序的示例代码

    前言 运营小姐姐说想要可以直接拖拽排序的功能,原来在序号六的广告可能会因为金主爸爸加钱换到序号一的位置,拖拽操作就很方便 效果 实现方式 template部分 <el-table v-loading="loading" :default-sort="{prop: 'sortNum', order: 'ascending'}" :data="list" border align="left" > <el-tab

  • Vue实用功能之实现拖拽元素、列表拖拽排序

    目录 Vue实现拖拽元素.列表拖拽排序 组件使用 补充:排序动画 总结 Vue实现拖拽元素.列表拖拽排序 需求:    1.左右两个容器,左边和右边的元素可以拖动互换    2.列表拖拽排序 组件使用 Vue.Draggable是一款基于Sortable.js实现的vue拖拽插件支持移动设备.拖拽和选择文本.智能滚动,可以在不同列表间拖拽.不依赖jQuery为基础,vue2过渡动画兼容.支持撤销操作,总之是一款非常优秀的vue拖拽组件 npm或yarn安装方式 yarn add vuedragg

  • js 实现div拖拽拉伸完整示例

    目录 前言 HTML CSS JS 前言 今天和大家分享一下.如何用js实现div拖拽拉伸等功能.功能比较简单,我就不赘述了.直接上代码. HTML <div class="resize" data-key="drag"> <img src="../images/liya.jpg" alt=""> <div class="line line-n" data-key="

随机推荐