React Draggable Elements List

非常簡易實作流程教學

Event

function onCLickHandler() {
	...
}

return (
  <button onClick={onCLickHandler} type="button">
  	demonstrate
  </button>
);
const ref = useRef();

useEffect(() => {
	if (!ref.current) return () => {};
    
    function onMouseEnterHandler() {
    	...
    }
    
    const { current } = ref;
    
    current.addEventListener('mouseenter', onMouseEnterHandler);
    
    return () => {
    	current.removeEventListener('mouseenter', onMouseEnterHandler);
    };
}, []);

return (
	<div ref={ref} />
);
提供處理user互動dom元素的媒介

Wrapper

Items

使用情境分三步驟
1. 點擊
2. 拖拉
3. 放開
點擊
Wrapper
1. 記錄itemId
2. clone clicked dom node
3. 加入mousemove, mouseup listener
Items
1. 加入mouseenter, mouseup listener
拖拉
Wrapper
1. 透過初始與當前x y座標計算top, left值
Items
1. mouseenter個別item時觸發排序function
放開
Wrapper
1. 初始化,並拔除listener
Items
1. 拔除listener

開始建立Package前...

1. 明確定義package功能,與未來擴充方向

針對element list做排序的package。
未來擴充:options-拖拉button功能、排序。animation-排序動畫、拖拉mode動畫

2. Guide doc ? demo example ? 使用工具?
為了加速開發,且套件規模不大,先緩
1. 明確定義package功能,與未來擴充方向

針對element list做排序的package。
未來擴充:options-拖拉button功能、排序。animation-排序動畫、拖拉mode動畫

2. Guide doc ? demo example ? 使用工具?
為了加速開發,且套件規模不大,先緩
3. 希望使用者如何使用package
<DraggableList>
  {items.map(item => (
  	<CustomizeDraggableItem item={item} />
  ))}
<DraggableList>

Component分層構思

DraggableElementsList:For user to use

DraggableElementsWrapper:For the dom clone and wrapper drag feature

...

...

DraggableElementPlacement:For the item drag feature

child

child

child

Using Render Props

<DraggableElementsWrapper>
  {({}) => draggableElements.map(({ returns, options }) => (
    <DraggableElementPlacement>
    	{children({ returns })}
    </DraggableElementPlacement>
  ))}
</DraggableElementsWrapper>

User Input & Output

Hook!

const mockItemBundle=[
	...bundleData,
]

const { DraggableList, draggableElements } = useDraggableElementsList(mockItemBundle);

<DraggableList>
  {({ item }) => (
  	<CustomizeDraggableItem item={item} />
  )}
<DraggableList>

DraggableElementsList:For user to use

DraggableElementsWrapper:For the dom clone and wrapper drag feature

...

...

DraggableElementPlacement:For the item drag feature

child

child

child

hook

useDraggableElementsList:For input, output & options

遇到的問題們

1. 遮罩問題

DraggableElementPlacement

原本Item內的按鈕功能會被遮罩擋住

解法1:透過額外的button來控制拖拉模式,進入拖拉模式時將placement拉至上層

透過按鈕來決定能不能拖拉這件事不直觀

解法2:使用react portal將item child轉到不同層的dom

因為placement為absolute蓋在上面,所以依舊有層級問題

解法1:透過額外的button來控制拖拉模式,進入拖拉模式時將placement拉至上層

透過按鈕來決定能不能拖拉這件事不直觀

解法2:使用react portal將item child轉到不同層的dom

因為placement為absolute蓋在上面,所以依舊有層級問題

DraggableElementsList

DraggableElementsWrapper

...

...

DraggableElementPlacement

child

child

child

useDraggableElementsList

ChildPlacementContainer

...

...

Placement

child

最終解:解法2+在child container中定義其底下包含特定classname的dom套用定義好的z-index

function CustomizeDraggableItem() {
  return (
    <div>
      <button
        type="button"
        className="react-draggable-element-list-triggerable">
        	triggerable-button
      </button>
    <div>
  );
}

DraggableElementsList

DraggableElementsWrapper

...

...

DraggableElementPlacement

child

child

child

useDraggableElementsList

ChildPlacementContainer

...

...

Placement

child

2. 拖拉功能實作方式

Event Emitter 建立頻道執行不同層的溝通觸發function建立event ?

優點:完全不會有props傳遞,useEffect用於一開始訂閱所需頻道,不用擔心預期外rerender

Wrapper傳遞setState, Items透過給予className與querySelector的方式取得ref

優點:較為單純,也不會同時建立一大堆eventListener

謝謝大家~

Reference:無

Made with Slides.com