先看效果
再看代码
utils.js
import Mock from 'mockjs'; // mock老师们数据 const data = Mock.mock({ 'list|10-40': [{ 'id|+1': 1, name: '@cname' }] }) // 模拟获取老师接口 export const getTeacher = () => { return Promise.resolve(data) } // 处理数据 适配tr->td export const groupByLen = (len, data) => { const res = []; for (let i = 0; i < data.length; i += len) { res.push(data.slice(i, i + len)); } return res; };
app.jsx
import { getTeacher, groupByLen } from './utils'; import { useEffect, useState } from 'react'; export default function App() { const [teachers, setTeachers] = useState([]); useEffect(() => { syncTable() }, []); const syncTable = async () => { const { list } = await getTeacher(); const res = groupByLen(6, list); setTeachers(res); } // 用户开始拖动元素时触发 const onDragstart = (e) => { console.log('开始移动', e.target); e.dataTransfer.setData("Text", e.target.id); } // 元素正在拖动时触发 const onDrop = (e) => { e.preventDefault(); const movedTargetId = e.dataTransfer.getData("Text"); const movedTarget = document.getElementById(movedTargetId); const movedTargetParent = movedTarget.parentNode; const receiveNodeName = e.target.nodeName; // 必须放到盒子里 if (receiveNodeName === 'TD') { movedTargetParent.appendChild(e.target.childNodes[0]); e.target.innerHTML = ''; e.target.appendChild(movedTarget); } else if (receiveNodeName === 'DIV') { const divParent = e.target.parentNode; movedTargetParent.appendChild(divParent.childNodes[0]); divParent.innerHTML = ''; divParent.appendChild(movedTarget); } } const allowDrop = (e) => { e.preventDefault(); } return ( <> <table> <tbody> {teachers.map((itemGroup, index) => (<tr key={index}> {itemGroup.map(item => (<td onDrop={onDrop} key={item.id} onDragOver={allowDrop}> <div id={item.id} onDragStart={onDragstart} draggable="true">{item.name}</div> </td>))} </tr>))} </tbody> </table> </> ) }