[React][TypeScript][HTML5]draggable拖曳排序

文、意如

在html標籤上加上屬性:draggable 即可拖曳

例:

<h4 draggable>::</h4>

<span draggable>拖曳</span>

只要在html標籤上加 draggable 這個屬性即可拖曳

超連結和圖片預設都是可拖曳的,不需要 draggable 屬性

 

 


在拖放的過程中會觸發以下事件:
在拖動目標上觸發事件 (源元素):
ondragstart - 用戶開始拖動元素時觸發
ondrag - 元素正在拖動時觸發
ondragend - 用戶完成元素拖動後觸發
釋放目標時觸發的事件:
ondragenter - 當被鼠標拖動的對象進入其容器範圍內時觸發此事件
ondragover - 當某被拖動的對像在另一對象容器範圍內拖動時觸發此事件
ondragleave - 當被鼠標拖動的對象離開其容器範圍內時觸發此事件
ondrop - 在一個拖動過程中,釋放鼠標鍵時觸發此事件
注意: 在拖動元素時,每隔 350 毫秒會觸發 ondragover 事件。

 

原始排序:

拖曳時

 

結束拖曳

程式碼:
test.tsx

import { useState } from "react";
import { DragIndicator, Autorenew } from '@mui/icons-material';
import { Button } from 'react-bootstrap';
export default function Test() {

  const [animal, setAnimal] = useState([
    "Cat",
    "Dog",
    "Fish",
    "Bird",
    "Monkey",
  ]);
  const [dragItemIndex, setDragItemIndex] = useState(0);
  const [dragOverItemIndex, setDragOverItemIndex] = useState(100);

  //開始拖曳
  function handleDragStart(index: any) {
    console.log("排序前陣列", animal)
    console.log("DragStart::", index)
    setDragItemIndex(index)
  }

  //拖曳釋放鼠標鍵時觸發此事件
  //正常情況下,物件不能放置到其他元素中。如果要實現改功能,我們需要防止元素的預設處理方法。
  //可通過調用 event.preventDefault() 方法來實現 ondragover 事件(將物件放置另一個物件(元素中))。
  function handleDragOver(event: any) {
    console.log("handleDragOver::")
    event.preventDefault();
  }
  //當拖曳的物件在另一個物件範圍即觸發
  function handleDrop() {
    console.log("handleDrop::::")
    const _animal = [...animal];
    console.log("排序前陣列", _animal);
    const dragItem = _animal.splice(dragItemIndex, 1);
    console.log("排序中");
    _animal.splice(dragOverItemIndex, 0, dragItem.toString());
    setAnimal(_animal);//新陣列
  }
  //用户完成物件拖曳後觸發
  function handleDragEnter(index: any) {
    console.log("handleDragEnter::index==", index)
    setDragOverItemIndex(index)
  }
  //結束拖曳
  function handleDragEnd(index: any) {
    console.log("完成拖曳==", index)
    console.log("old", dragItemIndex)
    console.log("newindex", dragOverItemIndex)
    console.log("排序後陣列", animal)
  }

  function reflash(e: any) {
    window.location.reload();
  }

  return (
    <div className='Title'>
      <Button onClick={(e) => reflash(e)}><Autorenew />重設</Button>
      <div className="list" >
        {animal.map((animal, index) => (
          <div
            key={index}
            style={{ width: '50%' }}
            className={dragOverItemIndex === index ? "next-position" : ""}//經過時顯示元素框
            draggable
            onDragStart={() => handleDragStart(index)}//開始拖曳
            onDragOver={handleDragOver} //當拖曳的物件在另一個物件範圍即觸發
            onDrop={() => handleDrop()} //拖曳釋放鼠標鍵時觸發此事件
            onDragEnter={() => handleDragEnter(index)}//用户完成物件拖曳後觸發
            onDragEnd={() => handleDragEnd(index)}//結束拖曳
          >
            <div style={{ backgroundColor: '#D0D0D0', margin: '10px' }}>
              <span><DragIndicator />排序{index}:{animal}</span>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

test.css

.next-position {
    border: 2px solid blue;
}

 

參考:https://www.runoob.com/jsref/event-ondragover.html

Yiru@Studio - 關於我 - 意如