最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用react-dnd編寫(xiě)一個(gè)可拖拽排列的list

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

今天的需求來(lái)啦:做一個(gè)可以通過(guò)拖拽排列的list。最終效果是這樣:

開(kāi)始之前,我找了個(gè)市面上比較主流的工具庫(kù),做個(gè)比對(duì):

react-beautiful-dnd

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

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

react-dnd的官方文檔介紹了如何做一個(gè)棋盤(pán),類(lèi)似的,這篇文章將介紹如何用react-dnd做一個(gè)draggable list。

Draggable

首先將list中的每一個(gè)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;

這樣我們?cè)赿emo中就能看到,這個(gè)組件就可以用鼠標(biāo)拖了:

Droppable

我們?cè)賹ist容器做成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;    //<--- 具體邏輯后面再寫(xiě),這里先設(shè)為true,即容器內(nèi)部一直是可以drop的。
  }

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

  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;

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

既是draggable,又是droppable

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

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

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

const dragDropRef = dragRef(dropRef(ref))

重排list

上一步我們把moveListItem傳給了父組件,那么在父組件中,我們可以這樣來(lái)改變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],
)

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

這樣一個(gè)sortable list就大功告成啦!

總結(jié)

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

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

相關(guān)文章

  • 淺談react性能優(yōu)化的方法

    淺談react性能優(yōu)化的方法

    這篇文章主要介紹了淺談react性能優(yōu)化的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • React?split實(shí)現(xiàn)分割字符串的使用示例

    React?split實(shí)現(xiàn)分割字符串的使用示例

    當(dāng)我們需要將一個(gè)字符串按照指定的分隔符進(jìn)行分割成數(shù)組時(shí),我們可以在組件的生命周期方法中使用split方法來(lái)實(shí)現(xiàn)這個(gè)功能,本文就來(lái)介紹一下,感興趣的可以了解下
    2023-10-10
  • React中重新實(shí)現(xiàn)強(qiáng)制實(shí)施表單的流程步驟

    React中重新實(shí)現(xiàn)強(qiáng)制實(shí)施表單的流程步驟

    這篇文章主要介紹了React中重新實(shí)現(xiàn)強(qiáng)制實(shí)施表單的流程步驟,就像設(shè)計(jì)人員一樣,在添加邏輯之前,您需要為不同的狀態(tài)“模擬”或創(chuàng)建“模擬”,例如,這里只是表單的視覺(jué)部分的模擬,文中通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2024-05-05
  • React 組件的狀態(tài)下移和內(nèi)容提升的操作方法

    React 組件的狀態(tài)下移和內(nèi)容提升的操作方法

    這篇文章主要介紹了React 組件的狀態(tài)下移和內(nèi)容提升,通過(guò)代碼講解了渲染性能的組件問(wèn)題結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • Redux Toolkit 實(shí)戰(zhàn)使用指南

    Redux Toolkit 實(shí)戰(zhàn)使用指南

    Redux Toolkit 是 Redux 官方推出的高效開(kāi)發(fā)工具集,本文就來(lái)介紹一下Redux Toolkit 實(shí)戰(zhàn)使用指南,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • React 首頁(yè)加載慢問(wèn)題性能優(yōu)化案例詳解

    React 首頁(yè)加載慢問(wèn)題性能優(yōu)化案例詳解

    這篇文章主要介紹了React 首頁(yè)加載慢問(wèn)題性能優(yōu)化案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • React配置代理服務(wù)器的5種方法及使用場(chǎng)景

    React配置代理服務(wù)器的5種方法及使用場(chǎng)景

    這篇文章主要介紹了React配置代理服務(wù)器的5種方法,無(wú)論使用哪種方法,都需要確保代理服務(wù)器的地址和端口正確,并且在配置完成后重新啟動(dòng)React開(kāi)發(fā)服務(wù)器,使配置生效,需要的朋友可以參考下
    2023-08-08
  • react-router?v6實(shí)現(xiàn)權(quán)限管理+自動(dòng)替換頁(yè)面標(biāo)題的案例

    react-router?v6實(shí)現(xiàn)權(quán)限管理+自動(dòng)替換頁(yè)面標(biāo)題的案例

    這篇文章主要介紹了react-router?v6實(shí)現(xiàn)權(quán)限管理+自動(dòng)替換頁(yè)面標(biāo)題,這次項(xiàng)目是有三種權(quán)限,分別是用戶(hù),商家以及管理員,這次寫(xiě)的權(quán)限管理是高級(jí)權(quán)限能訪問(wèn)低級(jí)權(quán)限的所有頁(yè)面,但是低級(jí)權(quán)限不能訪問(wèn)高級(jí)權(quán)限的頁(yè)面,需要的朋友可以參考下
    2023-05-05
  • 使用react+redux實(shí)現(xiàn)計(jì)數(shù)器功能及遇到問(wèn)題

    使用react+redux實(shí)現(xiàn)計(jì)數(shù)器功能及遇到問(wèn)題

    使用redux管理數(shù)據(jù),由于Store獨(dú)立于組件,使得數(shù)據(jù)管理獨(dú)立于組件,解決了組件之間傳遞數(shù)據(jù)困難的問(wèn)題,非常好用,今天重點(diǎn)給大家介紹使用react+redux實(shí)現(xiàn)計(jì)數(shù)器功能及遇到問(wèn)題,感興趣的朋友參考下吧
    2021-06-06
  • 每天學(xué)習(xí)一個(gè)hooks?useMount

    每天學(xué)習(xí)一個(gè)hooks?useMount

    這篇文章主要為大家介紹了每天學(xué)習(xí)一個(gè)hooks?useMount,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05

最新評(píng)論

固镇县| 兴城市| 大城县| 时尚| 正定县| 淳安县| 台湾省| 车致| 麦盖提县| 清徐县| 漯河市| 井冈山市| 林州市| 闽清县| 南丰县| 遂溪县| 周至县| 西吉县| 志丹县| 会理县| 桂东县| 台中县| 乌兰县| 伊金霍洛旗| 洛扎县| 定兴县| 保山市| 鹤壁市| 互助| 朝阳区| 佛冈县| 普格县| 泰宁县| 灵寿县| 通榆县| 中宁县| 远安县| 台东县| 松原市| 永嘉县| 文登市|