乐趣区

关于前端:为什么拖拽的-api-都很难用

最终成果

先来看达到了什么样的成果 https://github.com/mulcloud/s…

undo 操作

拖放到区域外主动回滚

Framer Motion 的毛病

拖拽和动画是由 Framer Motion 实现的。Framer Motion 在表白动画方面毫无疑问相当牛逼,一点点的代码,就能够实现十分丰盛的成果。比 react-spring 还要强!

Framer Motion 在拖拽方面要差点意思。这个是官网给的例子 https://codesandbox.io/s/framer-motion-2-drag-to-reorder-fc4rt。次要有两大毛病。

第一个毛病是短少 drag over 事件。HTML5 的 Drag/drop api 是有两局部的,一部分是被 drag 的元素,一部分是 dragging over 的元素。而 framer motion 仅仅提供了被 drag 元素的 dragStart 和 dragEnd 两个事件。这个就很不合乎直觉了,那我被 drag over 了,怎么显示我这里是能够被 drop 的呢?

第二个毛病是实现写得比拟绕。第 1 步先用 ref 拿到了 DOM 元素。第 2 步,在 useEffect 里采集每个 DOM 元素的地位,复制到另外一个名字叫 positions 的 useRef 上。第 3 步,假设一个 DOM 元素的数组就是界面上要排序的元素,进行元素地位调换。这相当于是把一部分的 DOM 状态做了一个残缺的拷贝,复制到了 react state 里。

为什么 react 拖拽库的 api 都不好用呢?

react dnd 也很难用 https://react-dnd.github.io/react-dnd/about

为啥这些 api 都不做得好用一点呢?我剖析有以下起因

  • react 的理念是 ui 由 state 渲染而来。然而拖拽的时候是找不到对应的 react state 的。
  • 间接操作 dom 的拖拽库,例如 https://github.com/SortableJS/Sortable 间接把 DOM 当 state 操作。然而这个和 react 渲染的界面又会抵触。须要做一些 hack 的工作能力让这样模式的拖拽库和 react 配合起来。
  • 跨列表拖拽等需要常常须要在多个组件之间挪动元素。这个时候是须要全局有 store 的,而不是每个组件各管各的状态。react 社区没有对立的全局 store,所以各个拖拽库只好让你来本人做适配了。
  • 拖拽过程的 placeholder/drop zone/ 辅助线 等各种交互成果都是有很重的业务逻辑的。这些业务逻辑重大依赖于 xy 坐标进行计算。然而 react 的代码里比拟难拿到 DOM 元素,以及 xy 坐标。须要 ref 和 useEffect 这样做一份复制。

间接拜访 DOM 就好了嘛

不能了解为啥用了 react,就肯定要啥都用 react。毕竟 Web DOM 的 api 还在那里啊,为啥不必呢?拖拽过程中计算元素地位,最不便最直观的,当然是间接用 DOM 的 api 获得鼠标上面的元素,而后拜访 offsetLeft / offsetHeight 等元素属性进行计算嘛。Framer Motion 的例子里复制一份有什么必要呢。如果有多个列表要拖拽,难道每个列表都要平行保护一份 DOM 的正本状态在 react state 中么?这也太原教旨主义了。

齐全托管状态

这个想法就是用一个“状态治理”工具把所有的组件状态都治理起来。这样就能很不便的实现 undo/redo 了。当然你会说,redux 就是这样的状态管理工具。

而且咱们心愿是多 store 的状态治理,对应到每个可被 draggable 和 droppable 的 DOM 都有一个 store。这个用 redux 就不那么间接了。为什么有多 store 的需要呢?因为后面间接拜访 DOM 做了排版上的计算,而后第二步就是要更新 state 触发重渲染了。咱们须要从 DOM 元素找到对应的 store,dispatch action 更新这个 store。一个直观的做法就是在 DOM 元素上加上 data-model-class 和 data-model-id 的属性,拿这两个属性去找到对应的 store。

最终实现的代码在这里 https://github.com/mulcloud/state-management-demo/tree/master/src/Scenario6

招聘前端

工作地点:北京 / 杭州

十分有创新性和成长的工作内容 https://www.zhipin.com/job_detail/?query=%E4%B9%98%E6%B3%95%E4%BA%91&city=101010100&industry=&position=

退出移动版