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

使用react-dnd編寫一個可拖拽排列的list

 更新時間:2024年03月15日 11:15:01   作者:利器之路  
這篇文章主要為大家詳細介紹了如何使用react-dnd編寫一個可拖拽排列的list,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

今天的需求來啦:做一個可以通過拖拽排列的list。最終效果是這樣:

開始之前,我找了個市面上比較主流的工具庫,做個比對:

react-beautiful-dnd

這個是atlassian用來開發(fā)jira看板功能的庫,有動畫效果,很漂亮,確實對得起這個包的名字。優(yōu)點是相對易用,而且好看,缺點是僅適合開發(fā)list一類的組件,而且?guī)啄昵熬鸵呀?jīng)不再維護了,對于新版的函數(shù)式react可能不太兼容。

  • dnd-kit這個是atlassian在棄用react-beautiful-dnd后重新維護的一個版本,效果是一樣的美麗,如果是web端的,還是很推薦的。
  • reat-dnd這是個比較全面的dnd庫,可以實現(xiàn)各種功能,要注意的是這是基于H5的開發(fā),如果你開發(fā)的端不是H5,可能不適用。

react-dnd的官方文檔介紹了如何做一個棋盤,類似的,這篇文章將介紹如何用react-dnd做一個draggable list。

Draggable

首先將list中的每一個item做成draggable組件。

引入useDrag

// ListItem.tsx
import { styled } from '@mui/material/styles';
import * as React from 'react';
import { useDrag } from 'react-dnd';

const StyledListItem = styled('div', {
  shouldForwardProp: prop => prop !== 'isDragging'
})<{ isDragging: boolean }>(({ isDragging, theme }) => ({
  opacity: isDragging ? 0.5 : 1,
  border: '1px blue solid',
}));

const ListItem = () => {
  const [{isDragging}, dragRef] = useDrag(() => ({
    type: 'listItem',
    collect: monitor => ({
      isDragging: !!monitor.isDragging(),
    }),
  }))

  return (
    <StyledListItem ref={dragRef} isDragging={isDragging}>
      list item
    </StyledListItem>
  )
}

export default ListItem;

這樣我們在demo中就能看到,這個組件就可以用鼠標(biāo)拖了:

Droppable

我們再將list容器做成droppable組件,這樣draggable組件才可以放在droppable的list里。

引入useDrop

// SortableList.tsx
import React, { forwardRef } from 'react';
import { useDrop } from 'react-dnd';
import ListItem from './components/listItem';

const SortableList = () => {

  const canMoveItem = () => {
    console.log('canMoveItem')
    return true;    //<--- 具體邏輯后面再寫,這里先設(shè)為true,即容器內(nèi)部一直是可以drop的。
  }

  const moveItem = () => {
    console.log('moveItem');    //<--- 具體邏輯后面再寫。
  }

  const [{ isOver, canDrop }, dropRef] = useDrop(
    () => ({
      accept: 'listItem',
      canDrop: () => canMoveItem(),
      drop: () => moveItem(),
      collect: (monitor) => ({
        isOver: !!monitor.isOver(),
        canDrop: !!monitor.canDrop()
      })
    }),
    [canMoveItem, moveItem]
  )
  
  return (
    <div>
      isOver: {String(isOver)}<br />
      canDrop: {String(canDrop)}
      <div
        ref={dropRef}
        style={{
          position: 'relative',
          width: '600px',
          height: '400px',
          border: '2px purple solid'
        }}
      >
        <ListItem></ListItem>
      </div>
    </div>
  );
}

export default SortableList;

這樣頁面上,我再容器內(nèi)部拖動時,isOvertrue,canDroptrue,拖到容器外isOver就變成false了:

既是draggable,又是droppable

當(dāng)有多個list item,可以通過拖拽調(diào)整順序,這樣我需要將list item也變成droppable

// ListItem.tsx
// 將list item也變成droppable
const [spec, dropRef] = useDrop({
    accept: 'listItem',
    hover: (item, monitor) => {
        const dragIndex = item.index
        const hoverIndex = index
        const hoverBoundingRect = ref.current?.getBoundingClientRect()
        const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
        const hoverActualY = monitor.getClientOffset().y - hoverBoundingRect.top

        // 如果是向下拖,只有當(dāng)hover的坐標(biāo)小于自身高度的一半時,繼續(xù)保持drag,否則相當(dāng)于要挪動其他的list item,給當(dāng)前的item騰個地方
        // if dragging down, continue only when hover is smaller than middle Y
        if (dragIndex < hoverIndex && hoverActualY < hoverMiddleY) return
        // 如果是向上拖,只有當(dāng)hover的坐標(biāo)大于自身高度的一半時,繼續(xù)保持drag,否則相當(dāng)于要挪動其他的list item,給當(dāng)前的item騰個地方
        if (dragIndex > hoverIndex && hoverActualY > hoverMiddleY) return
        moveListItem(dragIndex, hoverIndex)
        item.index = hoverIndex
    },
});

那么如何讓一個list item既是draggable,又是droppable呢?用以下方式:

// ListItem.tsx
const ref = useRef(null);

const dragDropRef = dragRef(dropRef(ref))

重排list

上一步我們把moveListItem傳給了父組件,那么在父組件中,我們可以這樣來改變list的順序:

// Mock data
const PETS = [
  { id: 1, name: 'dog' },
  { id: 2, name: 'cat' },
  { id: 3, name: 'fish' },
  { id: 4, name: 'hamster' },
]
// SortableList.tsx
const moveListItem = useCallback(
    (dragIndex, hoverIndex) => {
        console.log({dragIndex, hoverIndex})
        const dragItem = pets[dragIndex]
        const hoverItem = pets[hoverIndex]
        // 將PETS數(shù)組中,drag的item和hover的item交換位置
        setPets(pets => {
            const updatedPets = [...pets]
            updatedPets[dragIndex] = hoverItem
            updatedPets[hoverIndex] = dragItem
            return updatedPets
        })
    },
    [pets],
)

這樣我們就能得到這樣的效果:

這樣一個sortable list就大功告成啦!

總結(jié)

現(xiàn)在這個list是沒有任何動畫的,要是listItem在移動的過程中是有個過渡效果的,就顯得絲滑多了,那么接下來我將用react-flip-move將動畫效果加到每個item中。

到此這篇關(guān)于使用react-dnd編寫一個可拖拽排列的list的文章就介紹到這了,更多相關(guān)react-dnd可拖拽排列的list內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React+CSS 實現(xiàn)繪制橫向柱狀圖

    React+CSS 實現(xiàn)繪制橫向柱狀圖

    這篇文章主要介紹了React+CSS 實現(xiàn)繪制橫向柱狀圖,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • React高級特性Context萬字詳細解讀

    React高級特性Context萬字詳細解讀

    React的context就是一個全局變量,可以從根組件跨級別在React的組件中傳遞。React context的API有兩個版本,React16.x之前的是老版本的context,之后的是新版本的context
    2022-11-11
  • React如何解決樣式污染問題

    React如何解決樣式污染問題

    這篇文章主要介紹了React如何解決樣式污染問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • React動態(tài)更改html標(biāo)簽的實現(xiàn)方式

    React動態(tài)更改html標(biāo)簽的實現(xiàn)方式

    這篇文章主要介紹了React動態(tài)更改html標(biāo)簽的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Vite?+?React從零開始搭建一個開源組件庫

    Vite?+?React從零開始搭建一個開源組件庫

    這篇文章主要介紹了Vite?+?React?如何從0到1搭建一個開源組件庫,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • React之關(guān)于Promise的用法

    React之關(guān)于Promise的用法

    這篇文章主要介紹了React之關(guān)于Promise的用法及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • react滾動加載useInfiniteScroll?詳解

    react滾動加載useInfiniteScroll?詳解

    使用useInfiniteScroll?hook可以處理檢測用戶何時滾動到頁面底部的邏輯,并觸發(fā)回調(diào)函數(shù)以加載更多數(shù)據(jù),它還提供了一種簡單的方法來管理加載和錯誤消息的狀態(tài),今天通過實例代碼介紹下react滾動加載useInfiniteScroll?相關(guān)知識,感興趣的朋友跟隨小編一起看看吧
    2023-09-09
  • React?useEffect異步操作常見問題小結(jié)

    React?useEffect異步操作常見問題小結(jié)

    本文主要介紹了React?useEffect異步操作常見問題小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • React實現(xiàn)前端選區(qū)的示例代碼

    React實現(xiàn)前端選區(qū)的示例代碼

    本文主要介紹了React實現(xiàn)前端選區(qū)的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • React組件、狀態(tài)管理、代碼優(yōu)化的技巧

    React組件、狀態(tài)管理、代碼優(yōu)化的技巧

    文章總結(jié)了React組件設(shè)計、狀態(tài)管理、代碼組織和優(yōu)化的技巧,它涵蓋了使用Fragment、props解構(gòu)、defaultProps、key和ref的使用、渲染性能優(yōu)化等方面
    2024-11-11

最新評論