欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

react-dnd?API拖拽工具詳細用法示例

 更新時間:2022年10月17日 16:30:07   作者:Jou24  
這篇文章主要為大家介紹了react-dnd?API拖拽工具的詳細用法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

最近公司準備開發(fā)一個審批流系統(tǒng),其中會用到拖拽工具來搭建流程,關于拖拽的實現(xiàn)我們選擇了react-dnd這個庫,本文總結了react-dnd API的詳細用法,并附上不同場景的demo,希望對大家有用。

概念

React DnD 是一組 React 高階組件,使用的時候只需要使用對應的 API 將目標組件進行包裹,即可實現(xiàn)拖動或接受拖動元素的功能。

在拖動的過程中,不需要開發(fā)者自己判斷拖動狀態(tài),只需要在傳入的 spec 對象中各個狀態(tài)屬性中做對應處理即可,因為react-dnd使用了redux管理自身內部的狀態(tài)。

Some of these concepts resemble the Flux and Redux architectures.
This is not a coincidence, as React DnD uses Redux internally.

值得注意的是,react-dnd并不會改變頁面的視圖,它只會改變頁面元素的數(shù)據(jù)流向,因此它所提供的拖拽效果并不是很炫酷的,我們可能需要寫額外的視圖層來完成想要的效果,但是這種拖拽管理方式非常的通用,可以在任何場景下使用,非常適合用來定制。

核心API

介紹實現(xiàn)拖拽和數(shù)據(jù)流轉的核心API,這里以Hook為例。

DndProvider

如果想要使用 React DnD,首先需要在外層元素上加一個 DndProvider。

import { HTML5Backend } from 'react-dnd-html5-backend';
import { DndProvider } from 'react-dnd';
<DndProvider backend={HTML5Backend}>
    <TutorialApp />
</DndProvider>

DndProvider 的本質是一個由 React.createContext 創(chuàng)建一個上下文的容器(組件),用于控制拖拽的行為,數(shù)據(jù)的共享,類似于react-redux的Provider。

Backend

上面我們給DndProvider傳的參數(shù)是一個backend,那么這里來解釋一下什么是backend

React DnD 將 DOM 事件相關的代碼獨立出來,將拖拽事件轉換為 React DnD 內部的 redux action。由于拖拽發(fā)生在 H5 的時候是 ondrag,發(fā)生在移動設備的時候是由 touch 模擬,React DnD 將這部分單獨抽出來,方便后續(xù)的擴展,這部分就叫做 Backend。它是 DnD 在 Dom 層的實現(xiàn)。

  • react-dnd-html5-backend : 用于控制html5事件的backend
  • react-dnd-touch-backend : 用于控制移動端touch事件的backend
  • react-dnd-test-backend : 用戶可以參考自定義backend

useDrag

讓DOM實現(xiàn)拖拽能力的構子,官方用例如下

import { DragPreviewImage, useDrag } from 'react-dnd';
export const Knight: FC = () => {
    const [{ isDragging }, drag, preview] = useDrag(
        () => ({
            type: ItemTypes.KNIGHT,
            collect: (monitor) => ({
                isDragging: !!monitor.isDragging()
            })
        }),
        []
    );
    return (
        <>
            <DragPreviewImage connect={preview} src={knightImage} />
            <div
                ref={drag}
            >
                ?
            </div>
        </>
    );
};

useDrag返回三個參數(shù)

第一個返回值是一個對象 表示關聯(lián)在拖拽過程中的變量,需要在傳入useDrag的規(guī)范方法的collect屬性中進行映射綁定,比如:isDraging,canDrag等

第二個返回值 代表拖拽元素的ref

第三個返回值 代表拖拽元素拖拽后實際操作到的dom

useDrag傳入兩個參數(shù)

  • 第一個參數(shù),是一個對象,是用于描述了drag的配置信息,常用屬性

type: 指定元素的類型,只有類型相同的元素才能進行drop操作

item: 元素在拖拽過程中,描述該對象的數(shù)據(jù),如果指定的是一個方法,則方法會在開始拖拽時調用,并且需要返回一個對象來描述該元素。

end(item, monitor): 拖拽結束的回調函數(shù),item表示拖拽物的描述數(shù)據(jù),monitor表示一個 DragTargetMonitor 實例

isDragging(monitor):判斷元素是否在拖拽過程中,可以覆蓋Monitor對象中的isDragging方法,monitor表示一個 DragTargetMonitor 實例

isDragging: (monitor) => {
  return monitor.getItem() ? index === monitor.getItem().index : false;
},
collect: (monitor: any) => ({
    //當傳入isDragging方法時,monitor.isDragging()方法指代傳入的方法
  isDragging: monitor.isDragging(),
}),

canDrag(monitor):判斷是否可以拖拽的方法,需要返回一個bool值,可以覆蓋Monitor對象中的canDrag方法,與isDragging同理,monitor表示一個 DragTargetMonitor 實例

collect:它應該返回一個描述狀態(tài)的普通對象,然后返回以注入到組件中。它接收兩個參數(shù),一個 DragTargetMonitor 實例和拖拽元素描述信息item

  • 第二個參數(shù)是一個數(shù)組,表示對方法更新的約束,只有當數(shù)組中的參數(shù)發(fā)生改變,才會重新生成方法,基于react的useMemo實現(xiàn)

DragSourceMonitor對象

DragSourceMonitor是傳遞給拖動源的收集函數(shù)的對象。它的方法允許您獲取有關特定拖動源的拖動狀態(tài)的信息。 常用的方法: canDrag():描述元素是否可以拖拽,返回一個bool值

isDragging():判斷元素是否在拖拽過程中,返回一個bool值

getItemType():獲取元素的類型,返回一個bool值

getItem():獲取元素的描述數(shù)據(jù),返回一個對象

getDropResult():拖拽結束,返回拖拽結果的構子,可以拿到從drop元素中返回的數(shù)據(jù)

didDrop(): 拖拽結束,元素是否放置成功,返回一個bool值

getDifferenceFromInitialOffset(): 獲取相對于拖拽起始位置的相對偏移坐標。

useDrop

實現(xiàn)拖拽物放置的鉤子,官方用例如下

function BoardSquare({ x, y, children }) {
  const black = (x + y) % 2 === 1
  const [{ isOver }, drop] = useDrop(() => ({
    accept: ItemTypes.KNIGHT,
    drop: () => moveKnight(x, y),
    collect: monitor => ({
      isOver: !!monitor.isOver(),
    }),
  }), [x, y])
  return (
    <div
      ref={drop}
      style={{
        position: 'relative',
        width: '100%',
        height: '100%',
      }}
    >
     ....
    </div>,
  )
}
export default BoardSquare

useDrag返回兩個參數(shù)

  • 第一個返回值是一個對象,表示關聯(lián)在拖拽過程中的變量,需要在傳入useDrop的規(guī)范方法的collect屬性中進行映射綁定
  • 第二個返回值代表放置元素的ref

useDrop傳入一個參數(shù)

用于描述drop的配置信息,常用屬性

accept: 指定接收元素的類型,只有類型相同的元素才能進行drop操作

drop(item, monitor): 有拖拽物放置到元素上觸發(fā)的回調方法,item表示拖拽物的描述數(shù)據(jù),monitor表示 DropTargetMonitor實例,該方法返回一個對象,對象的數(shù)據(jù)可以由拖拽物的monitor.getDropResult方法獲得

hover(item, monitor):當拖住物在上方hover時觸發(fā),item表示拖拽物的描述數(shù)據(jù),monitor表示 DropTargetMonitor實例,返回一個bool值

canDrop(item, monitor):判斷拖拽物是否可以放置,item表示拖拽物的描述數(shù)據(jù),monitor表示 DropTargetMonitor實例,返回一個bool值

DropTargetMonitor對象

DropTargetMonitor是傳遞給拖放目標的收集函數(shù)的對象。它的方法允許您獲取有關特定拖放目標的拖動狀態(tài)的信息。 常用的方法:

canDrop():判斷拖拽物是否可以放置,返回一個bool值

isOver(options): 拖拽物掠過元素觸發(fā)的回調方法,options表示拖拽物的options信息

getItemType():獲取元素的類型,返回一個bool值

getItem():獲取元素的描述數(shù)據(jù),返回一個對象

didDrop(): 拖拽結束,元素是否放置成功,返回一個bool值

getDifferenceFromInitialOffset(): 獲取相對于拖拽起始位置的相對偏移坐標。

數(shù)據(jù)流轉

看了API之后,實際上不能很好的認識到每個狀態(tài)和每個方法的工作流程,所以,我這里畫了一張圖,幫助你更清晰的看到它的數(shù)據(jù)是如何流動的。

然后我們通過一個demo來更深刻的認識這個過程

這里我們定義了幾個單詞,然后通過拖拽,將它放入對應的分組里面

單詞代碼

const Word: FC = ({ type, text, id, ...props }: any) => {
  const [offsetX, setOffsetX] = useState(0);
  const [offsetY, setOffsetY] = useState(0);
  const [{ isDragging }, drag]: any = useDrag(() => ({
    type,
    item: { id, type },
    end(item, monitor) {
      let top = 0,
        left = 0;
      if (monitor.didDrop()) {
        const dropRes = monitor.getDropResult() as any;
        //獲取拖拽對象所處容器的數(shù)據(jù),獲取坐標變化
        if (dropRes) {
          top = dropRes.top;
          left = dropRes.left;
        }
        //這里必須寫成函數(shù)的傳入方式,否則無法獲取上一個state
        setOffsetX((offsetX) => offsetX + left);
        setOffsetY((offsetY) => offsetY + top);
      } else {
        // 移出則回到原位
        setOffsetX(0);
        setOffsetY(0);
      }
    },
    collect: (monitor) => ({
      isDragging: !!monitor.isDragging(),
    }),
  }));
  return ...   // dom
  );
};

分組代碼

function Classification({ type, title }: any) {
  const [{ isOver, canDrop }, drop] = useDrop(
    () => ({
      accept: type,
      drop(_item: any, monitor: any) {
         // 獲取每一次放置相對于上一次的偏移量
        const delta = monitor.getDifferenceFromInitialOffset();
        const left = Math.round(delta.x);
        const top = Math.round(delta.y);
        // 回傳給drag
        return { top, left };
      },
      canDrop: (_item, monitor) => {
        const item = monitor.getItem() as any;
        return item.type === type;
      },
      collect: (monitor) => ({
        isOver: !!monitor.isOver(),
        canDrop: !!monitor.canDrop(),
      }),
    }),
    [],
  );
  return ...   // dom
  )

完整demo戳鏈接:github.com/AdolescentJ…

拖拽預覽

受限于瀏覽器API的控制,拖拽元素在開始拖拽之后,只能保持其本身的一個樣式,不能使用其他樣式預覽,針對此,react-dnd為我們提供了兩種解決方法。

DragPreviewImage

react-dnd提供的DragPreviewImage組件,讓我們在拖拽的時候,可以以圖片的形式預覽拖拽的元素

它接收兩個參數(shù),一個是useDrag返回的預覽ref,一個是需要預覽的圖片

使用

import { useDrag, DragPreviewImage } from 'react-dnd';
import apple from '../../assets/apple.png';
const DragPreviewImg = () => {
  const [{ isDragging }, drag, preview] = useDrag({
    type: 'DragDropBox',
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });
  return (
    <>
      <DragPreviewImage connect={preview} src={apple} />
      <div
        className='card_drag'
        ref={drag}
        style={{
          opacity: isDragging ? 0.5 : 1,
        }}
      >
        drag item prview an apple
      </div>
    </>
  );
};
export default DragPreviewImg;

效果

完整demo戳鏈接:github.com/AdolescentJ…

使用圖片來預覽拖拽元素確實可以解決一部分問題,但在實際場景中,拖拽的元素可能會很多,我們也不能找UI把所有類型的圖都給一張,并且很多比較復雜的dom圖片是不能取代的

所以要展示更加定制化的預覽樣式,我們可以使用下面這種。

useDragLayer

useDragLayer是一個鉤子,它允許你使用dom的方式自定義拖拽元

它的原理是,監(jiān)聽你的拖拽狀態(tài),在拖拽的時候,可以取到你拖拽狀態(tài)的數(shù)據(jù),并且它會創(chuàng)建一個你想預覽的dom,然后我們可以可以通過拖拽的狀態(tài)來改變它的樣式,達到取代預覽的效果。

使用

const CustomDragLayer = (props: any) => {
//monitor 是drag的 monitor
    const { itemType, isDragging, item, initialOffset, currentOffset } = useDragLayer((monitor) => ({
        item: monitor.getItem(),
        itemType: monitor.getItemType(),
        initialOffset: monitor.getInitialSourceClientOffset(),
        currentOffset: monitor.getSourceClientOffset(),
        isDragging: monitor.isDragging(),
      }));
      if (!isDragging) {
        return null;
      }
      return (
        <div style={layerStyles}>
            <div className='card_drag'>這里是預覽樣式</div>
        </div>
      );
}

預覽

完整demo戳鏈接:github.com/AdolescentJ…

其他使用場景

除了上面的例子,還有非常多的案例

批量拖拽

可以選擇多個元素進行拖拽

拖拽排序

可以拖拽元素放置排序

完整demo戳鏈接:github.com/AdolescentJ…

最后

感謝你能看到這里,本文總結了react-dnd的API的使用以及常見的場景,希望對你有所幫助,后續(xù)會一直更新,當然,如果可以的話不妨留一個贊再走呢。

參考鏈接

react-dnd.github.io/react-dnd/d…

http://www.dbjr.com.cn/article/265220.htm

以上就是react-dnd API拖拽工具詳細用法示例的詳細內容,更多關于react-dnd API拖拽工具的資料請關注腳本之家其它相關文章!

相關文章

  • React中常見的動畫實現(xiàn)的幾種方式

    React中常見的動畫實現(xiàn)的幾種方式

    本篇文章主要介紹了React中常見的動畫實現(xiàn)的幾種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • React生命周期函數(shù)圖解介紹

    React生命周期函數(shù)圖解介紹

    生命周期函數(shù)指在某一時刻組件會自動調用并執(zhí)行的函數(shù)。React每個類組件都包含生命周期方法,以便于在運行過程中特定的階段執(zhí)行這些方法
    2022-11-11
  • react實現(xiàn)原生下拉刷新

    react實現(xiàn)原生下拉刷新

    這篇文章主要為大家詳細介紹了react實現(xiàn)原生下拉刷新,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • React自定義hook的方法

    React自定義hook的方法

    Hook是 React 16.8 的新增特性。它通常與函數(shù)式組件同時使用。可以使函數(shù)式組件在不編寫 class 的情況下,可以擁有class組件的狀態(tài)、生命周期、引用等功能,這篇文章主要介紹了React自定義hook的相關知識,需要的朋友可以參考下
    2022-06-06
  • 詳解react如何實現(xiàn)復合組件

    詳解react如何實現(xiàn)復合組件

    在一些react項目開發(fā)中,常常會出現(xiàn)一些組合的情況出現(xiàn),這篇文章主要為大家介紹了復合組件的具體實現(xiàn),感興趣的小伙伴可以跟隨小編一起學習一下
    2024-10-10
  • react使用echart繪制地圖的案例

    react使用echart繪制地圖的案例

    這篇文章主要介紹了react使用echart繪制地圖,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • react-diagram 序列化Json解讀案例分析

    react-diagram 序列化Json解讀案例分析

    今天帶來大家學習react-diagram 序列化Json解讀的相關知識,本文通過多種案例給大家分析序列化知識,通過圖文并茂的形式給大家介紹的非常詳細,感興趣的朋友一起看看吧
    2021-05-05
  • 淺談react?16.8版本新特性以及對react開發(fā)的影響

    淺談react?16.8版本新特性以及對react開發(fā)的影響

    本文主要介紹了react?16.8版本新特性以及對react開發(fā)的影響,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 關于React項目中的PDF展示解決方案

    關于React項目中的PDF展示解決方案

    這篇文章主要介紹了關于React項目中的PDF展示解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 瀏覽器中視頻播放器實現(xiàn)的基本思路與代碼

    瀏覽器中視頻播放器實現(xiàn)的基本思路與代碼

    這篇文章主要給大家介紹了關于瀏覽器中視頻播放器實現(xiàn)的基本思路與代碼,并且詳細總結了瀏覽器中的音視頻知識,對大家的理解和學習非常有幫助,需要的朋友可以參考下
    2021-08-08

最新評論