2023-06-11   


现在网上基于vue draggable做的表单设计器很多,很多布局相关的嵌套容器其作者都没有做相关的优化,我当时基于别人现成的表单设计器重写时也没有解决这些问题,现在有实力解决了,特地记一下一些需要注意的问题和解决方案

嵌套拖放区域需要有最小高度

当嵌套区域里内容为空时没有最小高度时会导致很难拖放到其中
解决方案:
嵌套容器设置min-height,同时使用overflow:hidden避免高度塌陷

嵌套容器拖放元素时无限抖动bug

这个问题我看网上目前基于vue draggable做的表单设计器都没有解决这个问题,都是属于用别的方式让这个bug不明显:
要么加过度动画时常让抖动不那么鬼畜,
要么就是设置拖放时的幽灵占位元素高度很小让bug不那么容易触发。
要么就是把嵌套容器底部的装饰区域移除(这个方法虽然可以也可以解决,但是表示选中的border也有1px的宽度,不换成outline也会触发bug,而且也不可能所有布局容器都把底部占位设置为0,不美观也不符合实际表单的预览)

bug原理:

因为布局容器都是利用嵌套的draggable容器实现。
表单设就差的嵌套的draggable容器一般周围都是由padding或margin或别的非可放置区域做装饰,当拖放元素从draggable容器经过,想拖入draggable容器里面放置时:

  1. 首先会经过draggable容器的非draggable区域
  2. 根据vue draggable的默认元素交换阈值设置,当前拖放元素会直接和draggable容器交换位置
  3. 交换位置过程中,draggable容器往下移动,拖放元素往上移动
  4. 拖放元素会经过draggable容器放置区域,然后元素就会进入draggable容器里
  5. 这时候拖放元素的在父容器的占位没有了,draggable容器终止往下移动,回到原来位置
  6. draggable容器往上回去原来位置时,因为拖放元素的鼠标始终不动(这里假设不动,因为不动才会触发),当回去原来位置时,拖放元素会离开draggable容器,重复步骤1
    于是就循环一直交换位置一直抖动。目前看github start最多的表单设计器是通过设置ghost元素为一个小横条,高度很小,这样交换位置的时候可能不会触发,因为人正常拖放操作时鼠标是一直在动的。但是这个问题根本没有实际上解决。(所以这些人对成果质量都没有追求的吗,毕竟有那么久了,虽然现在网上vue的表单设计器到处都是,但是都没有解决这个bug)
    如图:
    bug_example

现在说说解决这个问题本质的解决方式:

因为原因是vue draggable的默认元素交换阈值设置,只要拖放元素的鼠标经过交换元素就会立即触发交换,那么设置成经过交换元素中间才触发交换时就不会触发了bug了,因为触发bug的步骤2不会执行了。以下是Sortable.js(vue draggable基于它)官方文档关于交换阈值的demo:
http://sortablejs.github.io/Sortable/#thresholds
uTools_1686467947707
可以试着把交换阈值改成0.2再拖放元素,看看和默认值1的行为有啥不同。

Q.E.D.


我并不是什么都知道,我只是知道我所知道的。