Heim  >  Artikel  >  Web-Frontend  >  Von React DND implementierte Kartensortierfunktion (Codebeispiel)

Von React DND implementierte Kartensortierfunktion (Codebeispiel)

不言
不言nach vorne
2018-11-17 15:19:175710Durchsuche

Der Inhalt dieses Artikels befasst sich mit der von React DND implementierten Kartensortierfunktion. Ich hoffe, dass er für Sie hilfreich ist.

Als ich React im Unternehmen zum ersten Mal lernte, wurde ich in einer der Anforderungen aufgefordert, die Drag-and-Drop-Sortierfunktion zu implementieren. Nach Abschluss werde ich die Implementierungsmethode aufzeichnen und antd und ReactDND verwenden, um diese Funktion zu implementieren.

1. Umgebungseinrichtung

Verwenden Sie zunächst create-react-app Gerüst, um ein grundlegendes Reaktionsprojekt zu erstellen.

npm install -g create-react-app
create-react-app my-app
cd my-app

OK, das Reaktionsprojekt wird erstellt, und dann stellen wir antd vor, und react-dnd

$ yarn add antd
$ yarn add react-dnd
$ yarn add react-dnd-html5-backend

Nach dem Zitieren von antd können Sie das Laden bei Bedarf gemäß der Methode abschließen auf der offiziellen Website von andd.

2. Funktionsimplementierung

Wir verwenden zunächst antd, um eine einfache Kartenliste zu schreiben, ändern die Dateien APP.js und App.css im Projektverzeichnis und erstellen eine neue Datei CardItem.js

//App.js

import React, { Component } from 'react';
import CardItem from './CardItem'
import './App.css';

const CardList = [{ //定义卡片内容
    title:"first Card",
    id:1,
    content:"this is first Card"
  },{
    title:"second Card",
    id:2,
    content:"this is second Card"
  },{
    title:"Third Card",
    id:3,
    content:"this is Third Card"
  }
];
class App extends Component {
  state = {
    CardList
  }; 
  render() {
    return (
        <div>
            {CardList.map((item,index) => {
                return(
                    <carditem></carditem>
                )
            })}
        </div>
    );
  }
}

export default App;

//App.css

.card{
  display: flex;
  margin: 50px;
}
.card div{
  margin-right: 20px;
}

//CardItem.js

import React, { Component } from 'react';
import {Card} from 'antd'

class CardItem extends Component{
    render(){
        return(
            <div>
                <card>
                    <p>{this.props.content}</p>
                </card>
            </div>
        )
    }
}

export default CardItem

Okay, das Schreiben der Karte ist abgeschlossen, jetzt führen Sie unser Projekt aus und sehen den Effekt

$ npm start or yarn start

Von React DND implementierte Kartensortierfunktion (Codebeispiel)

OK, das Schreiben ist abgeschlossen, wir Jetzt müssen Sie mit react-dnd die Drag-and-Drop-Sortierung der Karten abschließen, sodass firstCard, secondCard und ThirdCard nach Belieben ausgetauscht werden können.

react-dnd bietet 3 APIs: DragDropContext, DragSource und DropTarget;

  • DragDropContext wird verwendet, um die Drag-Root-Komponente zu umschließen, DragSource und DropTarget beide müssen in DragDropContex

  • DropTarget eingeschlossen werden, um die Komponente einzuschließen, die Sie ziehen müssen, damit die Komponente gezogen werden kann

  • DragSource wird verwendet, um die Komponente zu umschließen, die das Drag-Element empfängt, sodass die Komponente platziert werden kann

Verstehen Die Rolle dieser APIs besteht darin, jede Karte in der Kartenliste auf DropTarget und DragSource zu setzen Schließlich, wenn das Ziehen abgeschlossen ist, ordnen Sie die Karten neu an, um die Implementierung dieser Funktion abzuschließen. Lassen Sie es uns Schritt für Schritt umsetzen.

Zuerst einrichten DragDropContext, App.js und react-dnd in react-dnd-html5-backend einführen (zuerst npm install dieses Plug-in)

//App.js

import React, { Component } from 'react';
import CardItem from './CardItem'
+ import {DragDropContext} from 'react-dnd'
+ import HTML5Backend from 'react-dnd-html5-backend'
import './App.css';

/*..
..*/

- export default App;
+ export default DragDropContext(HTML5Backend)(App);

Nun, es wird jetzt von der App verwendet .js Die umschlossenen Unterkomponenten können jetzt DropTarget und DragSource verwenden. Wir haben jetzt in der Unterkomponente CardItem React-DND festgelegt, sodass die Karte nun einen Drag-Effekt haben kann.

//CardItem.js

import React, { Component } from 'react';
import {Card} from 'antd'
+ import { //引入react-dnd
    DragSource,
    DropTarget,
} from 'react-dnd'


const Types = { // 设定类型,只有DragSource和DropTarget的类型相同时,才能完成拖拽和放置
    CARD: 'CARD'
};

//DragSource相关设定
const CardSource = {  //设定DragSource的拖拽事件方法
    beginDrag(props,monitor,component){ //拖拽开始时触发的事件,必须,返回props相关对象
        return {
            index:props.index
        }
    },
    endDrag(props, monitor, component){
      //拖拽结束时的事件,可选
    },
    canDrag(props, monitor){
      //是否可以拖拽的事件。可选
    },
    isDragging(props, monitor){
      // 拖拽时触发的事件,可选
    }
};

function collect(connect,monitor) { //通过这个函数可以通过this.props获取这个函数所返回的所有属性
    return{
        connectDragSource:connect.dragSource(),
        isDragging:monitor.isDragging()
    }
}

//DropTarget相关设定
const CardTarget = {
    drop(props, monitor, component){ //组件放下时触发的事件
        //...
    },
    canDrop(props,monitor){ //组件可以被放置时触发的事件,可选
        //...
    },
    hover(props,monitor,component){ //组件在target上方时触发的事件,可选
        //...
    },
    
};

function collect1(connect,monitor) {//同DragSource的collect函数
    return{
        connectDropTarget:connect.dropTarget(),
        isOver:monitor.isOver(), //source是否在Target上方
        isOverCurrent: monitor.isOver({ shallow: true }), 
        canDrop: monitor.canDrop(),//能否被放置
        itemType: monitor.getItemType(),//获取拖拽组件type
    }
}
class CardItem extends Component{

    render(){
        const { isDragging, connectDragSource, connectDropTarget} = this.props;
        let opacity = isDragging ? 0.1 : 1; //当被拖拽时呈现透明效果

        return connectDragSource( //使用DragSource 和 DropTarget
            connectDropTarget( <div> 
                <card>
                    <p>{this.props.content}</p>
                </card>
            </div> )
        )
    }
}

// 使组件连接DragSource和DropTarget
let flow = require('lodash.flow');
export default flow(
    DragSource(Types.CARD,CardSource,collect),
    DropTarget(Types.CARD,CardTarget,collect1)
)(CardItem)

Für die letzte Verbindungsmethode verweise ich auf die Anweisungen auf der offiziellen ReactDND-Website. Sie können sie auf der offiziellen Website von lodash.flow anzeigen und herunterladen.
Natürlich können Sie auch die Konstruktormethode als Referenz auswählen, z. B. @DragSource(type, spec, Collect) und @DropTarget(types, spec, Collect).

Auch wenn Sie nicht planen Um Dekoratoren zu verwenden, kann die Teilanwendung immer noch praktisch sein, da Sie mehrere DragSource- und DropTarget-Deklarationen in JavaScript mithilfe eines funktionalen Kompositionshilfsprogramms wie _.flow kombinieren können. Mit Dekoratoren können Sie einfach stapeln die
Dekoratoren, um den gleichen Effekt zu erzielen.

import { DragSource, DropTarget } from 'react-dnd';
import flow from 'lodash/flow';

class YourComponent {
  render() {
    const { connectDragSource, connectDropTarget } = this.props
    return connectDragSource(connectDropTarget(
      /* ... */
    ))
  }
}

export default flow(
  DragSource(/* ... */),
  DropTarget(/* ... */)
)(YourComponent);

Da wir nun die Implementierung eines Drag-Effekts abgeschlossen haben, werfen wir einen Blick auf den Effekt

Von React DND implementierte Kartensortierfunktion (Codebeispiel)Sie können den Effekt des Ziehens deutlich erkennen. Als nächstes müssen wir die Sortierfunktion nach dem Ziehen und Platzieren abschließen. Wir fügen die Sortierfunktion in App.js ein und rufen sie in der Hover-Funktion im CardTarget-Konstruktor in CardItem.js auf. Als nächstes schauen wir uns die spezifische Implementierungsmethode an.

//CardItem.js

const CardTarget = {
    hover(props,monitor,component){
        if(!component) return null; //异常处理判断
        const dragIndex = monitor.getItem().index;//拖拽目标的Index
        const hoverIndex = props.index; //放置目标Index
        if(dragIndex === hoverIndex) return null;// 如果拖拽目标和放置目标相同的话,停止执行
        
        //如果不做以下处理,则卡片移动到另一个卡片上就会进行交换,下方处理使得卡片能够在跨过中心线后进行交换.
        const hoverBoundingRect = (findDOMNode(component)).getBoundingClientRect();//获取卡片的边框矩形
        const hoverMiddleX = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;//获取X轴中点
        const clientOffset = monitor.getClientOffset();//获取拖拽目标偏移量
        const hoverClientX = (clientOffset).x - hoverBoundingRect.left;
        if (dragIndex  hoverIndex && hoverClientX > hoverMiddleX) { // 从后往前放置
            return null
        }
        props.DND(dragIndex,hoverIndex); //调用App.js中方法完成交换
        monitor.getItem().index = hoverIndex; //重新赋值index,否则会出现无限交换情况
    }
}
rrree

Okay, jetzt haben wir es Ich habe eine kleine Demo der Kartensortierfunktion fertiggestellt. Schauen wir uns den Effekt an!

Von React DND implementierte Kartensortierfunktion (Codebeispiel)

Das obige ist der detaillierte Inhalt vonVon React DND implementierte Kartensortierfunktion (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen