時(shí)間:2024-01-26 06:45:01 | 來源:網(wǎng)站運(yùn)營
時(shí)間:2024-01-26 06:45:01 來源:網(wǎng)站運(yùn)營
React組件可視化拖拽頁面搭建,源碼生成,你有什么想法?:正好有篇文章可以參考:本文主要內(nèi)容
draggable="true"
的屬性即可,另外,超鏈接和圖像都是默認(rèn)可拖動的。ondragstart
、ondragenter
、ondragover
、ondragleave
等等各階段發(fā)生在元素上的拖動事件,最后還需要處理ondrop
事件完成最終的放置,我們需要做好數(shù)據(jù)的傳遞,可放置區(qū)域的識別、最終位置的處理,頁面的更新等等一系列細(xì)小繁瑣的工作。backend
,monitor
,drag
,drop
。import { HTML5Backend } from 'react-dnd-html5-backend'import { DndProvider, useDrag, useDrop } from 'react-dnd'function Drag() { const [collectedProps, drag] = useDrag({ item: { values, type: 'KEY' } }) return ( <div ref={drag}>Drag</div> )}function Drop() { const [collectedProps, drop] = useDrop({ accept: 'KEY' }) return ( <div ref={drop}>Drop Area</div> )}export default function Demo() { return ( <DndProvider backend={HTML5Backend}> <Drag /> <Drop /> </DndProvider> )}
react-dnd-html5-backend
,否則就使用react-dnd-touch-backend
,注意DndProvider
一定是在Drag和Drop的最外層使用的。draggable=true
的屬性,同時(shí)拖動的所有事件都會被我們監(jiān)聽到。使用方法可以參考上面例子。const [collectedProps, drag] = useDrag({item, canDrag, collect})
useDrag返回的數(shù)組一共有三個(gè)元素,我們只說前兩個(gè):collectedProps: 這其實(shí)是React-DnD一個(gè)很精妙的設(shè)計(jì),組件在拖動的時(shí)候,此變量便代表著需要監(jiān)聽的數(shù)據(jù)drag: 即拖動元素的Ref引用,賦給對應(yīng)的DOM元素即可
useDrag的函數(shù)參數(shù)也很多,這里只挑重要的說一下:item: 必填,即包含的數(shù)據(jù)對象,必須字段type,與drop對象對應(yīng),只有同一個(gè)type值的才能被放置進(jìn)去canDrag: 選填,(monitor) => boolean,表示是否可拖拽,這在區(qū)分編輯與只讀模式非常有用collect: 選填,(monitor) => object,通過此方法返回的值可以從上述的collectedProps中取到, 通過使用monitor判斷狀態(tài),我們可以返回如opacity、hightlighted等屬性用來給拖動元素添加樣式
const [collectedProps, drop] = useDrop({ accept, hover, drop, collect })
其中參數(shù)和返回值如下:collectedProps: 同上,也是collect函數(shù)返回的objectdrop: 即放置元素的Ref引用,賦給對應(yīng)的DOM元素即可
useDrop的參數(shù)也很多,我們也挑重點(diǎn)的說明一下:accept: 必填,支持字符串或者字符串?dāng)?shù)組,對應(yīng)于drag的type值,同樣的值才可被拖入此元素中hover: 選填,(item, monitor) => void,item即拖動到此drop上drag對象的值,通過用于展示滑上后的預(yù)覽效果drop: 選填,(item, monitor) => void,同上,此事件在鼠標(biāo)放開后觸發(fā)collect: 選填,(monitor) => object,作用同上,也可以用來表達(dá)drag進(jìn)來和離開事件
至此所有的react-dnd基本概念已經(jīng)介紹完了,正所謂“九層之臺起于累土,千里之行始于足下”,頁面上的所有交互都是基于這些最基本的功能實(shí)現(xiàn)的,也許你仍然覺得很抽象,不妨參考下官網(wǎng)的Demo其中Sandbox的代碼例子來學(xué)習(xí)一下,擠需體驗(yàn)十番鐘,里造會干我一樣,愛象節(jié)款工具!resize
來支持拉伸,比如常見的textarea就是默認(rèn)內(nèi)置了此屬性,但是瀏覽器并未像drag一樣提供resize專門的API,故大部分庫都是通過監(jiān)聽mousedown
,mousemove
,mouseup
這種有些hack的方式完成的。grid
來設(shè)置步長,如果要做定制化的對齊就麻煩了,這里分享一個(gè)思路,我們可以在onResize或onResizeStop的時(shí)候,通過參數(shù)我們可以獲取偏移位置,此時(shí)可以對偏移位置進(jìn)行計(jì)算后四舍五入,便可保證按比例變化。document.elementFromPoint(x,y)
方法,通過不斷加步長迭代的方式應(yīng)該可以找到最近的子元素并獲取對應(yīng)的寬高。TYPE="Container"拖拽源容器即所有可供用戶拖拽到畫布上的容器布局,所有的組件應(yīng)當(dāng)被放置到容器內(nèi)進(jìn)行布局上的管理,如果組件能實(shí)現(xiàn)良好的布局管理其實(shí)也可以不需要此容器。
TYPE="Widget"即實(shí)際業(yè)務(wù)上需要的展示組件,這部分是支持二次開發(fā)的,且用了Form-Render 支持以配置項(xiàng)的方式生成組件配置表單,組件只需要關(guān)注業(yè)務(wù)邏輯,配置項(xiàng)會自動注入進(jìn)來。
TYPE="PaintContainer" ACCEPT=["Container", "PaintContainer"]當(dāng)把拖拽源拖入畫布后,即生成一個(gè)畫布容器區(qū)域,也可以不用一個(gè)新的TYPE,這樣做主要是便于快速區(qū)分是從拖拽源過來的或是畫布上模塊的移動,如果想讓一個(gè)DOM同時(shí)支持Drag & Drop,可以這樣做:
const ref = useRef();const [,drop] = useDrop({});const [,drag] = useDrag({});drop(drag(ref));return <div ref={ref}> Both Can Drag & Drop </div>
TYPE="PaintWidget" ACCEPT=["Widget", "PaintWidget"]這里也可以用兩個(gè)不同的TYPE來區(qū)分,區(qū)分從拖拽源進(jìn)來的還是從畫布上別的地方拖進(jìn)來的,一個(gè)是把數(shù)據(jù)填充進(jìn)去,一個(gè)是交換兩個(gè)位置的下標(biāo)。
{ uuid: string; // 唯一標(biāo)識區(qū)塊的id width,height... // 定位與尺寸屬性 children: { // 里面的子展示組件 uuid: string; // 唯一標(biāo)識展示組件的id span: number; // 展示組件占寬度 widgetId: string; // 具體是哪一個(gè)展示組件,渲染時(shí)會取組件列表中獲取并渲染 config: object; // 個(gè)性化配置項(xiàng)值 }[] }
這里不得不贊美一下React的 Render(data) => View 模式做這種畫布實(shí)在太合適了,每次只要修改了數(shù)據(jù)結(jié)構(gòu),React就會自動根據(jù)數(shù)據(jù)結(jié)構(gòu)渲染出畫布里具體的內(nèi)容,少操了很多心。[ { data: '2020-09-01', type: 'A', count: 5 }, { data: '2020-09-03', type: 'A', count: 15 }, { data: '2020-09-03', type: 'B', count: 10 }, { data: '2020-09-06', type: 'C', count: 20 },]
上面的數(shù)據(jù),缺少了9月2日和9月4日,9月5日的數(shù)據(jù),如果不把空缺的時(shí)間填上去,那橫軸間隔就會很奇怪。responseData數(shù)組
,總種類數(shù)為M,分享一個(gè)O(NM)時(shí)間復(fù)雜度的方法(因?yàn)樽罱K數(shù)組長度就是N*M,所以應(yīng)該還是蠻高效的)dayjs工具
生成從查詢起始時(shí)間到終止時(shí)間的時(shí)間序列數(shù)組dateList
,元素為日期stringresultList
,參考Echarts規(guī)范,這個(gè)數(shù)組的格式為{ type: value[] },type就是狀態(tài)值,value的下標(biāo)是日期的下標(biāo),值是count數(shù)據(jù)dateList
第0
個(gè)元素,下標(biāo)指針j指向responseData
第0
個(gè)元素resultList[Enum(M)][i]
賦值resultList[Enum(M)][i] || 0
dateList[i]
和responseData[j]
對應(yīng)的日期是否一樣,如果一樣,則跳轉(zhuǎn)到第六步,否則到第七步resultList[type][i]
為responseData[j].count
,這里的type是responseData[j].type
,然后j++
,因?yàn)檫€要在結(jié)果中找尋同一個(gè)日期下其他數(shù)據(jù),接著返回第四步i++
,然后返回第四步i
超過dateList
的長度后,終止循環(huán)即可關(guān)鍵詞:
客戶&案例
營銷資訊
關(guān)于我們
微信公眾號
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。