Le contenu de cet article concerne la fonction de tri des cartes (exemple de code) implémentée par React DND. Elle a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Lorsque j'ai appris React pour la première fois dans l'entreprise, l'une des exigences m'a demandé d'implémenter la fonction de tri par glisser-déposer. Une fois terminé, j'enregistrerai la méthode d'implémentation et j'utiliserai antd et reactDND pour implémenter cette fonction.
Tout d'abord, utilisez create-react-app
un échafaudage pour créer un projet de réaction de base.
npm install -g create-react-app create-react-app my-app cd my-app
OK, le projet React est construit, puis nous introduisons antd
, et react-dnd
$ yarn add antd $ yarn add react-dnd $ yarn add react-dnd-html5-backend
Après avoir cité antd, vous pouvez suivre la méthode sur le. antd site officiel pour terminer le pressage Doit être chargé.
Nous utilisons d'abord antd pour écrire une simple liste de cartes, modifier les fichiers APP.js et App.css dans le répertoire du projet et créer un nouveau fichier 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
D'accord, l'écriture de la carte est terminée, maintenant lancez notre projet et voyez l'effet
$ npm start or yarn start
OK , Après avoir écrit, ce que nous devons faire maintenant est d'utiliser react-dnd
pour terminer le tri par glisser-déposer des cartes, afin que firstCard, secondCard et ThirdCard puissent être échangées à volonté.
react-dnd fournit 3 API : DragDropContext, DragSource et DropTarget ;
DragDropContext est utilisé pour envelopper le composant glisser racine, DragSource
et DropTarget
les deux doivent être enveloppés dans DragDropContex
DropTarget est utilisé pour envelopper le composant que vous devez faire glisser afin que le composant puisse être déplacé
DragSource est utilisé pour envelopper le composant qui reçoit l'élément glisser, afin que le composant puisse être placé
Comprendre le rôle de ces API, L'idée générale de construire un tri de cartes a émergé. Comment mettre en œuvre un tri de cartes est en fait très simple, il s'agit de définir chaque carte de la liste de cartes sur DropTarget
et DragSource
, et. enfin, lorsque le glisser est terminé, réorganisez les cartes pour terminer la mise en œuvre de cette fonction. Mettons-le en œuvre étape par étape.
Premier ensemble DragDropContext
, introduisez App.js
et react-dnd
dans react-dnd-html5-backend
(d'abord npm install
ce 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);
D'accord, maintenant c'est l'application. Les sous-composants enveloppés dans js peuvent désormais utiliser DropTarget et DragSource. Nous définissons désormais réagir-dnd dans le sous-composant CardItem afin que la carte puisse désormais avoir un effet de glissement.
//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)
Pour la dernière méthode de connexion, je me réfère aux instructions sur le site officiel de reactDND. Vous pouvez vous rendre sur le site officiel de lodash.flow pour le consulter et le télécharger.
Bien sûr, vous pouvez également choisir la méthode du constructeur pour référence, telle que @DragSource(type, spec, collect) et @DropTarget(types, spec, collect).
Même si vous ne prévoyez pas pour utiliser des décorateurs, l'application partielle peut
encore être pratique, car vous pouvez combiner plusieurs déclarations DragSource et
DropTarget en JavaScript à l'aide d'un assistant de composition fonctionnel
tel que _.flow Avec les décorateurs, vous pouvez simplement empiler. les
décorateurs pour obtenir le même effet.
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);
Maintenant que nous avons terminé la mise en œuvre d'un effet de traînée, jetons un œil à l'effet
Vous pouvez clairement voir l'effet du glisser. Ensuite, nous devons terminer la fonction de tri après le glisser et le placer.
Nous mettons la fonction de tri dans App.js et l'appelons dans la fonction de survol dans le constructeur CardTarget dans CardItem.js. Examinons ensuite la méthode d'implémentation spécifique.
//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,否则会出现无限交换情况 } }
//App.js handleDND = (dragIndex,hoverIndex) => { let CardList = this.state.CardList; let tmp = CardList[dragIndex] //临时储存文件 CardList.splice(dragIndex,1) //移除拖拽项 CardList.splice(hoverIndex,0,tmp) //插入放置项 this.setState({ CardList }) }; /* ... */ //添加传递参数传递函数 <carditem></carditem>
. Bon, maintenant que nous avons terminé une petite démo de la fonction de tri des cartes, jetons un œil à l'effet !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!