react拖拽react-beautiful-dnd一維數(shù)組二維數(shù)組拖拽功能
寫(xiě)在前邊,二維數(shù)組可以拖拽,但是不可以編輯+拖拽,如果想要實(shí)現(xiàn)編輯+拖拽,還是需要轉(zhuǎn)換成一維數(shù)組。原因是因?yàn)椴寮墓俜揭?guī)定,在拖拽過(guò)程中不可以編輯Droppable層的Props。
相關(guān)地址:
中文文檔地址
react-beautiful-dnd - 《react-beautiful-dnd 中文文檔幫助手冊(cè)教程》 - 極客文檔 (geekdaxue.co)
git源碼
GitHub - chinanf-boy/react-beautiful-dnd-zh: ????翻譯: react-beautiful-dnd 文檔 ?? 更新 ?
使用
安裝
# yarn yarn add react-beautiful-dnd # npm npm install react-beautiful-dnd --save
引入
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
引用
<DraggableList data={listDemo}></DraggableList>
一維數(shù)組使用
傳參data是一維數(shù)組
import React, { useEffect, useState } from 'react'; import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd'; interface Props { data: any[]; } const DraggableList: React.FC<Props> = ({ data }) => { const [sortList, setSortList] = useState([]); const getItems = () => { const arr = Array.from({ length: 10 }, (v, k) => k).map((k) => ({ id: `item-${k}`, content: `item ${k}`, })); setSortList(arr); }; useEffect(() => { getItems(); }, []); const grid = 8; const getItemStyle = (isDragging, draggableStyle) => ({ // some basic styles to make the items look a bit nicer userSelect: 'none', padding: grid * 2, margin: `0 ${grid}px 0 0`, // change background colour if dragging background: isDragging ? 'lightgreen' : 'grey', // styles we need to apply on draggables ...draggableStyle, }); const getListStyle = (isDraggingOver: any) => ({ background: isDraggingOver ? 'lightblue' : 'lightgrey', display: 'flex', padding: grid, overflow: 'auto', }); const onDragEnd = (result) => { if (!result.destination) { return; } console.log('end', sortList, result); const res = sortList.filter((item) => item); // 更改引用地址 console.log('移動(dòng)前res', res); const [removed] = res.splice(result.source.index, 1); console.log('刪除???', removed); res.splice(result.destination.index, 0, removed); console.log('添加后', res); setSortList(res); }; console.log('data', data); /** * Draggable組件可以拖動(dòng)并拖放到其Droppables上. 一個(gè)Draggable必須始終包含在一個(gè)Droppable. * 它是 可能重新排序Draggable在其Droppable家中或移動(dòng)到另一個(gè)Droppable. * 一個(gè)Draggable必須包含在一個(gè)Droppable. * */ return ( <DragDropContext onDragEnd={onDragEnd}> <Droppable droppableId="droppable" direction="horizontal"> {(provided, snapshot) => ( <div ref={provided.innerRef} style={getListStyle(snapshot.isDraggingOver)} {...provided.droppableProps}> {sortList.map((item, index) => ( <Draggable key={item.id} draggableId={item.id} index={index}> {(provided, snapshot) => ( <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)} > {item.content} </div> )} </Draggable> ))} {provided.placeholder} </div> )} </Droppable> </DragDropContext> ); }; export default DraggableList;
二維數(shù)組的使用
import React, { useEffect, useState } from 'react'; import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd'; interface Props { data: any[]; } const DraggableList: React.FC<Props> = ({ data = [] }) => { const [sortList, setSortList] = useState(data); const grid = 8; const getItemStyle = (isDragging, draggableStyle) => ({ // some basic styles to make the items look a bit nicer userSelect: 'none', padding: grid * 2, margin: `0 ${grid}px 0 0`, // change background colour if dragging background: isDragging ? 'lightgreen' : 'grey', // styles we need to apply on draggables ...draggableStyle, }); const getListStyle = (isDraggingOver) => ({ background: isDraggingOver ? 'lightblue' : 'lightgrey', display: 'flex', padding: grid, overflow: 'auto', }); const onDragEnd = (result) => { if (!result.destination) { return; } console.log('end', sortList, result); const res = sortList.filter((item) => item); //修改引用地址 console.log('res', res); const [removed] = res.splice(result.source.index, 1); console.log('刪除???', removed); res.splice(result.destination.index, 0, removed); console.log('添加后', res); setSortList(res); }; useEffect(() => { setSortList(data); }, [data]); console.log('data', data); return ( <DragDropContext onDragEnd={onDragEnd}> {sortList.map((item, index) => { return ( <Droppable droppableId={'droppable' + index} key={index} direction="vertical"> {(provided, snapshot) => ( <div ref={provided.innerRef} style={getListStyle(snapshot.isDraggingOver)} {...provided.droppableProps}> {/*{data.map((item, index) => (*/} <Draggable key={item[0].value} draggableId={item[0].value} index={index}> {(provided, snapshot) => ( <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)} > {66666 + item[0].label} </div> )} </Draggable> {/*))}*/} {provided.placeholder} </div> )} </Droppable> ); })} </DragDropContext> ); }; export default DraggableList;
組件傳值的數(shù)組內(nèi)容
const [options, setOptions] = useState([ { label: '延時(shí)時(shí)間', value: 'delayTime', children: [ { label: '時(shí)', value: 'hour', disabled: false, }, { label: '分', value: 'minute', disabled: false, }, { label: '秒', value: 'second', disabled: false, }, ], }, { label: '限制類(lèi)型', value: 'limitType', children: [ { label: '前置點(diǎn)位1', value: '1', disabled: false, }, { label: '前置點(diǎn)位2', value: '2', disabled: false, }, { label: '前置點(diǎn)位3', value: '3', disabled: false, }, ], }, { label: '溫度', value: 'templete', }, ]);
案列
案例是通過(guò)級(jí)聯(lián)的組件選擇條件,新增條件時(shí),前端重新定義數(shù)據(jù)格式,將二維的結(jié)構(gòu)改成一維數(shù)組的結(jié)構(gòu)。遍歷填充內(nèi)容時(shí),是在Droppable的下一級(jí),所以可以修改內(nèi)容。
const onDispatchValue = (res: any) => { dispatch({ type: `${MODEL_NAME}/save`, payload: { proTypeList: res, }, }); }; // 新增、刪除前置條件 const [inputFlag, setInputFlag] = useState(false); const [listDemo, setListDemo] = useState([]); const changeCondition = (ids, option) => { let arr2 = []; // 第三層關(guān)系選中兩個(gè)時(shí)的判斷 if (ids && ids.length > 1) { // 二維數(shù)組結(jié)構(gòu)成一維數(shù)組,方便去重 arr2 = ids.reduce((a, b) => { return a.concat(b); }); const arr3 = Array.from(new Set(arr2)); if (arr2.length !== arr3.length) { setRepeatFlag(true); return message.warning('前置條件重復(fù),請(qǐng)刪除!'); } else { setRepeatFlag(false); } } // 沒(méi)有子級(jí)或者全選的判斷 ids.map((item, index) => { if (item.length === 1 && option[index][0].value === item[0] && option[index][0]?.children?.length > 0) { setRepeatFlag(true); return message.warning('前置條件重復(fù),請(qǐng)刪除!'); } else { setRepeatFlag(false); } }); const arr = option.map((item) => { let obj = { typeName: '', // 類(lèi)型名稱(chēng) typeValue: '', // 類(lèi)型id unitName: '', // 單位名稱(chēng) unitValue: '', // 單位id value: '', // 值 }; item.map((i, index) => { if (item.length === 1) { obj.typeName = i.label; obj.typeValue = i.value; } if (item.length === 2) { if (index === 1) { obj.unitName = i.label; obj.unitValue = i.value; } else { obj.typeName = i.label; obj.typeValue = i.value; } } }); return obj; }); setListDemo(arr); // 保存定義好的數(shù)據(jù),用于組件之間傳值 onDispatchValue(arr); };
// 父組件引用 <DraggableList data={proTypeList}></DraggableList>
// 子組件 import { ConnectState } from '@/typing/connect'; import { connect } from '@@/exports'; import { Input } from 'antd'; import React, { useEffect, useState } from 'react'; import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd'; import { Dispatch } from 'umi'; interface Props { data: any[]; dispatch: Dispatch; } const MODEL_NAME = 'mainConfig'; const DraggableList: React.FC<Props> = ({ data = [], dispatch }) => { const [sortList, setSortList] = useState(data); // 拖拽時(shí)的樣式 const getListStyle = () => ({ overflow: 'auto', width: '100%', }); // 拖拽后的樣式 const getItemStyle = (isDragging, draggableStyle) => ({ // some basic styles to make the items look a bit nicer width: '100%', userSelect: 'none', ...draggableStyle, }); const onDragEnd = (result) => { if (!result.destination) { return; } const res = sortList.filter((item) => item); //修改引用地址 const [removed] = res.splice(result.source.index, 1); res.splice(result.destination.index, 0, removed); // console.log('添加后', res); setSortList(res); dispatch({ type: `${MODEL_NAME}/save`, payload: { proTypeList: res, }, }); console.log('拖拽后', res); }; // 校驗(yàn)輸入框內(nèi)容 const regInputValue = (e: any, index: number) => { // 輸入框聚焦時(shí) const arr = data.filter((item) => item); arr[index].value = e.target.value; console.log('arr', arr); setSortList(arr); dispatch({ type: `${MODEL_NAME}/save`, payload: { proTypeList: arr, }, }); }; useEffect(() => { setSortList(data); }, [data]); // console.log('彈窗起落data', data); /** * Draggable組件可以拖動(dòng)并拖放到其Droppables上. 一個(gè)Draggable必須始終包含在一個(gè)Droppable. * 它是 可能重新排序Draggable在其Droppable家中或移動(dòng)到另一個(gè)Droppable. * 一個(gè)Draggable必須包含在一個(gè)Droppable. * */ return ( <DragDropContext onDragEnd={onDragEnd}> <Droppable droppableId="droppable" direction="horizontal"> {(provided, snapshot) => ( <div ref={provided.innerRef} style={getListStyle(snapshot.isDraggingOver)} {...provided.droppableProps}> {data.map((item, index) => ( <Draggable key={item.typeValue} draggableId={item.typeValue} index={index}> {(provided, snapshot) => ( <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)} > <div style={{ width: '100%', display: 'flex', justifyContent: 'flex-start', textAlign: 'center' }}> <div style={{ width: '33%', backgroundColor: '#f2f2f2', padding: '8px 0' }}>條件名稱(chēng)</div> <div style={{ width: '33%', backgroundColor: '#f2f2f2', padding: '8px 0' }}>條件值</div> <div style={{ width: '33%', backgroundColor: '#f2f2f2', padding: '8px 0' }}>單位名稱(chēng)</div> </div> <div style={{ width: '100%', display: 'flex', justifyContent: 'flex-start', padding: '6px', textAlign: 'center', marginBottom: 16, }} > <div style={{ width: '33%', padding: '8px 0' }}>{item.typeName}</div> <div style={{ width: '33%', padding: '8px 0' }}> <Input placeholder="請(qǐng)輸入內(nèi)容" onChange={(e) => { regInputValue(e, index); }} /> </div> <div style={{ width: '33%', padding: '8px 0' }}>{item.unitName}</div> </div> </div> )} </Draggable> ))} {provided.placeholder} </div> )} </Droppable> </DragDropContext> ); }; export default connect(({ mainConfig }: ConnectState) => ({ mainConfig , }))(DraggableList);
到此這篇關(guān)于react拖拽react-beautiful-dnd,一維數(shù)組,二維數(shù)組的文章就介紹到這了,更多相關(guān)react拖拽react-beautiful-dnd,一維數(shù)組,二維數(shù)組內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react native實(shí)現(xiàn)往服務(wù)器上傳網(wǎng)絡(luò)圖片的實(shí)例
下面小編就為大家?guī)?lái)一篇react native實(shí)現(xiàn)往服務(wù)器上傳網(wǎng)絡(luò)圖片的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08React中重新實(shí)現(xiàn)強(qiáng)制實(shí)施表單的流程步驟
這篇文章主要介紹了React中重新實(shí)現(xiàn)強(qiáng)制實(shí)施表單的流程步驟,就像設(shè)計(jì)人員一樣,在添加邏輯之前,您需要為不同的狀態(tài)“模擬”或創(chuàng)建“模擬”,例如,這里只是表單的視覺(jué)部分的模擬,文中通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下2024-05-05react-native中路由頁(yè)面的跳轉(zhuǎn)與傳參的實(shí)例詳解
這篇文章主要介紹了react-native中路由頁(yè)面的跳轉(zhuǎn)與傳參,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08React工作流程及Error Boundaries實(shí)現(xiàn)過(guò)程講解
這篇文章主要介紹了React工作流程及Error Boundaries實(shí)現(xiàn)過(guò)程講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-02-02React Native 啟動(dòng)流程詳細(xì)解析
這篇文章主要介紹了React Native 啟動(dòng)流程簡(jiǎn)析,文以 react-native-cli 創(chuàng)建的示例工程(安卓部分)為例,給大家分析 React Native 的啟動(dòng)流程,需要的朋友可以參考下2021-08-08React使用Context與router實(shí)現(xiàn)權(quán)限路由詳細(xì)介紹
這篇文章主要介紹了React使用Context與router實(shí)現(xiàn)權(quán)限路由的詳細(xì)過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-01-01