在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美

當前位置:雨林木風下載站 > 網頁設計教程 > 詳細頁面

React DND完成的卡片排序技巧(代碼示例)

React DND完成的卡片排序技巧(代碼示例)

更新時間:2025-12-08 文章作者:未知 信息來源:網絡 閱讀次數:

網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立...
網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立在超文本基礎之上的。超級文本標記語言之所以稱為超文本標記語言,是因為文本中包含了所謂“超級鏈接”點。
本篇文章給大家帶來的內容是關于React DND實現的卡片排序功能(代碼示例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

在公司初學react,其中一個要求讓我實現拖拽排序的功能,完成之后記錄一下實現方法,采用antd和reactDND來實現這個功能。

一、環境搭建

首先,使用 create-react-app 腳手架創建一個最基本的react項目。

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

OK,構建好了react項目,然后我們引入antd,和react-dnd

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

引用完antd后可以按照antd官網上的方法完成按需加載。

二、功能實現

我們先使用antd寫出一個簡單的卡片列表,修改項目目錄的APP.js和App.css文件,新建一個文件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 className='card'>
            {CardList.map((item,index) => {
                return(
                    <CardItem //向次級界面傳遞參數
                        key={item.id}
                        title={item.title}
                        content={item.content}
                        index={index}
                    />
                )
            })}
        </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
                    title={this.props.title}
                    style={{ width: 300 }}
                >
                    <p>{this.props.content}</p>
                </Card>
            </div>
        )
    }
}

export default CardItem

好了,卡片編寫完成了,現在運行一下我們的項目,看一下效果

$ npm start or yarn start

990746295-5bef6f6c2c95f_articlex.png

OK,編寫完成,我們現在要做的就是使用react-dnd完成卡片的拖拽排序,使得firstCard,secondCard,thirdCard可以隨意的交換。

react-dnd中提供了DragDropContext,DragSource,DropTarget 3種API;

  • DragDropContext 用于包裝拖拽根組件,DragSourceDropTarget 都需要包裹在DragDropContex

  • DropTarget 用于包裝你需要拖動的組件,使組件能夠被拖拽

  • DragSource 用于包裝接收拖拽元素的組件,使組件能夠放置

理解了這些API的作用,一個卡片排序的構建思路大體就浮現出來了,怎么樣實現一個卡片排序,其實很簡單,就是把卡片列表中的每一個卡片都設置為DropTargetDragSource,最后在拖拽結束的時候進行卡片之間的重排序,完成這一功能的實現。下面我們就來一步一步的實現它。

首先設定DragDropContext,在App.js中引入 react-dndreact-dnd-html5-backend(先npm install這個插件)

//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);

好了,現在被App.js所包裹的子組件都可以使用DropTarget和DragSource了,我們現在在子組件CardItem中設定react-dnd使得卡片現在能夠有拖動的效果。

//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
                    title={this.props.title}
                    style={{ width: 300 ,opacity}}
                >
                    <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)

最后這個連接方法我參考了 reactDND官網 的說明,你可以去 lodash.flow的官網 進行查看并下載。
當然你也可以選擇構造器的方法進行引用,如@DragSource(type, spec, collect)和@DropTarget(types, spec, collect).

Even if you don't plan to use decorators, the partial application can
still be handy, because you can combine several DragSource and
DropTarget declarations in JavaScript using a functional composition
helper such as _.flow. With decorators, you can just stack the
decorators to achieve the same effect.

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);

現在我們已經完成了一個拖拽效果的實現,現在我們來看一下效果

2836309455-5bef8b2e0522d_articlex.png

可以很明顯的看到拖拽帶來的效果,接下來我們要完成拖拽放置后的排序函數。
我們將排序函數放在App.js當中,在CardItem.js中的CardTarget構造方法中的hover函數中進行調用,接下來看具體的實現方法.

//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
        }
        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 //向次級界面傳遞參數
        key={item.id}
        title={item.title}
        content={item.content}
        index={index}
        onDND={this.handleDND}
    />

好了,現在我們已經完成了一個卡片排序功能的小demo,讓我們來看一下效果吧!

3687378792-5befb7045bd2a_articlex.gif

以上就是React DND實現的卡片排序功能(代碼示例)的詳細內容,更多請關注php中文網其它相關文章!


網站建設是一個廣義的術語,涵蓋了許多不同的技能和學科中所使用的生產和維護的網站。

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統下載排行

在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美
  • <li id="86scu"><menu id="86scu"></menu></li>
    <li id="86scu"></li>
    <button id="86scu"></button>
  • <s id="86scu"></s><button id="86scu"><menu id="86scu"></menu></button>
  • 久久久久久综合网| 欧美女人性生活视频| 久久久999视频| 国内精品视频一区二区三区| 日韩不卡视频一区二区| 欧美在线a视频| 亚洲综合欧美激情| 中文字幕精品一区二区三区在线| 欧美午夜精品理论片| 日本激情视频在线播放| 能在线观看的av网站| 国产小视频精品| 无套内谢丰满少妇中文字幕| 少妇性l交大片| 五月婷婷激情久久| 国产福利精品一区二区三区| 色播五月综合网| 午夜福利123| 性生活免费观看视频| 国产美女主播在线| 欧美私人情侣网站| 天天爱天天做天天操| 免费大片在线观看| 美女网站免费观看视频| 国产一区二区四区| 国产一区二区三区精彩视频 | 丰满少妇大力进入| 黄色永久免费网站| 久久久精品视频国产| www.国产二区| 日韩精品视频网址| 成人在线免费观看视频网站| 日本黄色福利视频| 久久久久久久少妇| 天堂av免费看| 国内自拍在线观看| 无套内谢丰满少妇中文字幕| 无码粉嫩虎白一线天在线观看| aa在线免费观看| 天堂av手机在线| 无码人妻丰满熟妇区毛片18| 天天影视色综合| 日日橹狠狠爱欧美超碰| 红桃视频 国产| 欧美日韩亚洲第一| 91看片淫黄大片91| 91女神在线观看| 六月丁香婷婷在线| 欧美大黑帍在线播放| 中文字幕 日韩 欧美| 欧美 丝袜 自拍 制服 另类| 日本特级黄色大片| 青少年xxxxx性开放hg| 精品国产免费av| www.亚洲成人网| 最新免费av网址| 91看片在线免费观看| 国产av天堂无码一区二区三区| 一区二区三区四区毛片| 亚洲国产精品毛片av不卡在线| 特级西西人体www高清大胆| 奇米视频7777| 亚洲色图38p| 成年网站在线免费观看| 青青艹视频在线| 777久久精品一区二区三区无码 | 亚洲美女性囗交| 欧美亚洲日本在线观看| 欧美成人三级在线视频| 女人床在线观看| 女人帮男人橹视频播放| 欧美日韩午夜爽爽| 丰满的少妇愉情hd高清果冻传媒| 善良的小姨在线| 8x8ⅹ国产精品一区二区二区| 婷婷激情小说网| 一级特黄妇女高潮| 久久综合亚洲精品| 日本aa在线观看| 人妻av中文系列| av动漫在线看| 亚洲天堂网一区| 女人高潮一级片| 日本高清xxxx| av女优在线播放| 无码精品国产一区二区三区免费| 日韩精品 欧美| 免费男同深夜夜行网站| 最新国产黄色网址| 中文字幕人妻熟女人妻洋洋| 可以在线看的av网站| 日韩欧美xxxx| 四虎成人在线播放| 国产午夜福利在线播放| 性欧美极品xxxx欧美一区二区| 日本人视频jizz页码69| 欧美日韩一级在线| 亚洲中文字幕无码av永久| 日韩av播放器| 欧洲美女和动交zoz0z| 精品国产免费av| 亚洲日本黄色片| 黄色动漫在线免费看| 日韩视频在线观看一区二区三区| 国产手机免费视频| 手机av在线网| 欧美 激情 在线| 影音先锋成人资源网站| 国产v亚洲v天堂无码久久久| 最新黄色av网站| 亚洲精品中文字幕无码蜜桃| 看一级黄色录像| 日日噜噜夜夜狠狠| 成人性免费视频| 热久久最新地址| 天天操天天干天天做| 久草青青在线观看| 精品人妻大屁股白浆无码| 午夜剧场在线免费观看| 欧美精品成人网| 激情伊人五月天| 男人天堂手机在线视频| 日韩不卡的av| 日本高清免费在线视频| 欧洲熟妇精品视频| 国产第一页视频| 日韩久久一级片| 无码播放一区二区三区| 免费高清一区二区三区| 韩国黄色一级大片| 国产大尺度在线观看| 婷婷激情综合五月天| 高潮一区二区三区| 国产三级国产精品国产专区50| 日韩精品无码一区二区三区免费| 欧美午夜性视频| 日韩xxxx视频| 成人一对一视频| 亚洲熟妇av一区二区三区| 欧美s码亚洲码精品m码| 青青艹视频在线| 日韩 欧美 高清| 久久国产激情视频| 国产无色aaa| 中文字幕乱码免费| 2018国产在线| 手机看片福利日韩| mm131亚洲精品| 亚洲天堂一区二区在线观看| av在线网站免费观看| 人人妻人人澡人人爽欧美一区| 国产一区二区三区乱码| 久久成人免费观看| 天天色综合社区| 警花观音坐莲激情销魂小说| 日韩极品视频在线观看| 日本免费一级视频| 中文 日韩 欧美| 日本韩国欧美在线观看| 欧美精品一区二区三区免费播放| 国产三级三级看三级| 一本久道高清无码视频| av免费中文字幕| 97超碰人人爱| av免费网站观看| 亚洲色婷婷久久精品av蜜桃| 日本丰满少妇xxxx| 日本黄色福利视频| 日韩精品xxxx| 国产成年人在线观看| 国产成人精品视频免费看| 国产传媒免费观看| 黄色一级片播放| www亚洲国产| 亚洲久久中文字幕| 精品视频在线观看一区二区| 免费裸体美女网站| 蜜臀精品一区二区| 奇米视频888| 成人综合视频在线| 亚洲国产精品女人| 美女在线视频一区二区| 久久精品免费一区二区| 成人手机视频在线| 久久精品网站视频| 青青草精品视频在线| 国产资源第一页| 桥本有菜av在线| 污污的网站免费| 欧美成人免费高清视频| 男女视频网站在线观看| 青青视频免费在线观看| 亚洲午夜激情影院| www.涩涩涩| 在线观看亚洲色图| 欧美日韩在线不卡视频| 噜噜噜久久亚洲精品国产品麻豆| 国产91在线亚洲| 国产香蕉一区二区三区| 久久久一二三四|