React 拖拽排序

这篇文章基本骨架来自:文件点击上传和拖拽上传

今天我们要解决的问题就是页面上我们上传了多个文件,我们需要怎么实现移动拖拽排序的效果。

借用插件,先安装:

npm install --save react-sortable

参考官方文档:https://www.npmjs.com/package/react-sortable
实现效果:

拖拽排序

思路:

  • 要求每个图片必须是一个单独的组件
    图片组件配置一共三步:
import React, { Component } from 'react'
// ①引包
import {sortable} from "react-sortable";
// ②装饰器语法进行组件装饰,注意这个装饰器就一个圆括号
// ③根 div 加上{...this.props}
@sortable
export default class Sortable extends Component {
    render() {
        return (
            <div className = "cur" {...this.props}>
                <img src = {this.props.base64}/>
            </div>
        )
    }
}

如果不使用@这个语法糖就得这样写:

import React, { Component } from 'react'
// ①引包
import {sortable} from "react-sortable";
// ③根 div 加上{...this.props}

class Sortable extends Component {
    render() {
        return (
            <div className = "cur" {...this.props}>
                <img src = {this.props.base64}/>
            </div>
        )
    }
}
// ②装饰器语法进行组件装饰,注意这个装饰器就一个圆括号
export default sortable(Sortable)

到这里拖拽图片的话基本就可看见拖拽效果,但是还不能看到排序的效果。

  • 父组件也得三步操作,操作的地方就在子组件上
{
    this.state.base64.map((item,index) => <Sortable key = {index} base64 = {item} 
    onSortItems={(arr)=>{
        this.setState({
            base64:arr
        })
    }}
    items={this.state.base64}
    sortId={index}
    />)
}

第一个地方:给子组件一个 sortId 一般 key 用啥就给它啥
第二个地方:items 给它的值就是当前进行 map 的数组
第三个地方:一个函数,很明显是使用排序好的数组来更新当前数组

没啦配置完成。

以下是 2019年08月29日的补充

二、react 拖拽的进化

上面的拖拽是非常的简单,特别像我以前使用原生 JS 模仿简书后台写的一个九宫格拖拽。这种有一个缺点,没有动画,在重视用户体验的情况下,这种插件是万万不能用的。其实实现动画原理也特别的简单,再源码在加个动画延迟就行了。今天在看 react-sortable npm 官网的时候,发现它推荐了两个动画特别流畅的 npm 包。react-sortable-hocreact-beautiful-dnd 。随便选一个用一下,react-sortable-hoc的下载量高一点就用它了。开始:

  • 安装两个插件
npm install --save react-sortable-hoc
npm install --save array-move

先解释第二个:
array-move 就一个 API,它的主要作用就是用来交换数组中元素的位置。我们用 node 进行调试 1.js 文件,调试结果如下:

// 引包
const arrayMove = require('array-move');
// 创建一个数组
const input = ['a', 'b', 'c'];
 
// 以下三个排序实例
console.log(arrayMove(input, 1, 2));
//=> ['a', 'c', 'b']
 
console.log(arrayMove(input, -1, 0));
//=> ['c', 'a', 'b']
 
console.log(arrayMove(input, -2, -3));
//=> ['b', 'a', 'c']

node 1.js 运行文件,控制台输出结果如下:

C:\Users\Administrator\Desktop\my>node 1.js
[ 'a', 'c', 'b' ]
[ 'c', 'a', 'b' ]
[ 'b', 'a', 'c' ]
  • 高阶函数
    在熟练使用 react-sortable-hoc 之前,先熟悉高阶函数。

高阶函数的定义简单来讲就是:高阶函数(Higher Order Function)=> 参数或返回值为函数

我们常见的有数组的遍历方式 Map、Reduce、Filter、Sort;常用的 redux 中的 connect 方法也是高阶函数。

这里在补充一个专有名词:函数的 柯里化

维基百科上:Currying(柯里化)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

说白了就是一个函数调用的时候形参至少多余一个,柯里化就是在保证函数功能不变的情况下,把函数调用的形参限定只能是一个。

看一个简单加法器的案例:

//普通加法函数
function add(x,y){
    return x + y;
}
add(8,9);

// 柯里化
function add(x){
    // x这里属于闭包的概念
    return function(y){
        return x + y;
    }
}
add(8)(9);

这玩意有啥用那,有函数不就行了?

可以提高函数的复用,例如一个字符串多次进行不同类型的正则查询。这个过程又有一个概念叫预处理

请看演示:

// 正常正则验证字符串 reg.test(txt)

// 函数封装后
function check(reg, txt) {
    return reg.test(txt)
}

check(/\d+/g, 'abc')       //false
check(/[a-z]+/g, 'abc')    //true

// 柯里化
function curryingCheck(txt) {
    return function(reg) {
        return reg.test(txt)
    }
}

let has = curryingCheck("从我a1b2c3d4ef里面筛选只筛选出数字或字母!");
// 柯里化不像普通函数一样老是需要传入形参txt
has(/\d+/g); //true
has(/[a-z]/g)//true
  • react-sortable-hoc 使用
    react-sortable-hoc 提供了两个特别重要的 API ,分别是SortableContainer 和 SortableElement 看英文的意思也知道,SortableElement用来装饰每个要拖拽的组件,相对于SortableContainer 要装饰的组件,SortableElement 装饰的组件是子组件。

  • SortableElement 提供了一个 index 属性来进行子组件排序。

  • SortableContainer 提供一个方法 onSortEnd 。这个函数可以结构两个形参。{oldIndex, newIndex} 一个是拖拽元素的标记,一个是将要放的那个地方标记。最后在使用 arrayMove 交换数组的位置。axis 是拖拽的方向,默认是 y ,垂直拖拽,x 表示只可以水平拖拽。

搞清楚这些上案例:
文件夹的逻辑结构就是 App.js 请求数据,数据是个数组传给子组件 B (用SortableContainer装饰),孙子组件 A 来呈现图片(用SortableElement装饰),另外本案例使用了语法糖@SortableContainer 完全可以替换为 SortableContainer(组件)

父组件:App.js

import React, { Component } from 'react';
import B from "./B";
import { SortableContainer } from 'react-sortable-hoc';
import arrayMove from 'array-move';
import axios from "axios";
export default class App extends Component {
    constructor(){
        super();
        this.state = {
            arr : [105,106,107]
        }
    }
    render() {
        this.onSortEnd = ({oldIndex, newIndex}) => {
            this.setState({
                arr: arrayMove(this.state.arr, oldIndex, newIndex)
            });
        };
        return (
            <div>
                <B arr={this.state.arr} axis="x" onSortEnd={this.onSortEnd}/>
            </div>
        )
    }
}

子组件 B.js

import React, { Component } from 'react';
import A from "./A";
import { SortableContainer } from 'react-sortable-hoc';
@SortableContainer
export default class B extends Component {
    constructor(){
        super();
    }
    render() {
        return (
            <div>
                {this.props.arr.map((item,index)=><A collection="沙雕" key={item} item={item} index={index} onSortEnd={this.onSortEnd}/>)}
            </div>
        )
    }
}

孙子组件A.js:

import React, { Component } from 'react';
import { sortableElement } from 'react-sortable-hoc';
@sortableElement
export default class A extends Component {
    constructor(){
        super();
    }
    render() {
        return (
            <div style={{"float":"left"}}>
                {<img src={`./images/${this.props.item}.jpg`}/>}
            </div>
        )
    }
}

运行效果:


react-sortable-hoc
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 深入JSX date:20170412笔记原文其实JSX是React.createElement(componen...
    gaoer1938阅读 8,026评论 2 35
  • 今天的React题没有太多的故事…… 半个月前出了248个Vue的知识点,受到很多朋友的关注,都强烈要求再出多些R...
    浪子神剑阅读 10,020评论 6 105
  • 探索Vue高阶组件 高阶组件(HOC)是 React 生态系统的常用词汇,React 中代码复用的主要方式就是使用...
    君惜丶阅读 952评论 0 2
  • 钟悦悦一开始并不是做HR的,以前每次找工作,去到每一家公司,前台美女都让她填《应聘登记表》,尽管她已经带打印版简历...
    芳姐育儿阅读 5,076评论 0 3
  • 父亲出院以来,基本上都是卧床休息。我仔细观察他的神态,觉得他身体状况还好。虽然手术过后身体还有些虚弱,但是...
    冯俊龙阅读 506评论 1 5