先来看达到了什么样的效果 https://github.com/mulcloud/s...前端
undo 操做react
拖放到区域外自动回滚git
拖拽和动画是由 Framer Motion 实现的。Framer Motion 在表达动画方面毫无疑问至关牛逼,一点点的代码,就能够实现很是丰富的效果。比 react-spring 还要强!github
Framer Motion 在拖拽方面要差点意思。这个是官方给的例子 https://codesandbox.io/s/framer-motion-2-drag-to-reorder-fc4rt 。 主要有两大缺点。spring
第一个缺点是缺乏 drag over 事件。HTML5 的 Drag/drop api 是有两部分的,一部分是被 drag 的元素,一部分是 dragging over 的元素。而 framer motion 仅仅提供了被 drag 元素的 dragStart 和 dragEnd 两个事件。这个就很不符合直觉了,那我被 drag over 了,怎么显示我这里是能够被 drop 的呢?redux
第二个缺点是实现写得比较绕。第1步先用 ref 拿到了 DOM 元素。第2步,在 useEffect 里采集每一个 DOM 元素的位置,复制到另一个名字叫 positions 的 useRef 上。第3步,假定一个 DOM 元素的数组就是界面上要排序的元素,进行元素位置互换。这至关因而把一部分的 DOM 状态作了一个完整的拷贝,复制到了 react state 里。api
react dnd 也很难用 https://react-dnd.github.io/react-dnd/about数组
为啥这些 api 都不作得好用一点呢?我分析有如下缘由dom
不能理解为啥用了 react,就必定要啥都用 react。毕竟 Web DOM 的 api 还在那里啊,为啥不用呢?拖拽过程当中计算元素位置,最方便最直观的,固然是直接用 DOM 的 api 取得鼠标下面的元素,而后访问 offsetLeft / offsetHeight 等元素属性进行计算嘛。Framer Motion 的例子里复制一份有什么必要呢。若是有多个列表要拖拽,难道每一个列表都要平行维护一份 DOM 的副本状态在 react state 中么?这也太原教旨主义了。ide
这个想法就是用一个“状态管理”工具把全部的组件状态都管理起来。这样就能很方便的实现 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=