vue3项目中最简单的拖拽实现节点位置变化

时间:2024-10-22 10:30:43

vue3 项目中实现拖拽位置最简单的方法

大家实现拖拽可能都会用到这个组件vuedraggable 其他版本,但是使用起来比较麻烦,例如我想在antd-vue中实现菜单位置的随意切换,并且其中菜单有些使用了自定义插槽的话,使用起来就很麻烦,而且很难实现,尤其有些使用v-draggable指令更是很难实现。
拖拽排序
以上效果,既要实现对选中的列进行显隐控制,还要实现拖拽排序。这里面利用antd-menu-组件,菜单项包裹了Checkbox-group组件

<Menu multiple v-model:selectedKeys="">
   <Checkbox-group v-model:value="">
     <Menu.Item :key="'all'" v-if="">
       <Checkbox :value="'all'" @change="menuChange">{{ props.allText }}</Checkbox>
     </Menu.Item>
     <!--还有其他配置项-->
   </Checkbox-group>
 </Menu>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这个时候,如果想实现拖拽排序的话,draggable低版本组件本身就很难帮我们实现了。

vue-draggable-next 升级版

官网:/vue-draggable-next/ 中文版
这个组件用起来就很方便了。他是对vuedraggable组件的升级,也是再vue3 中实用的(特别是vue setup 语法)

<Draggable
  v-if=""
  class="dragArea"
  :list=""
  @change="onDragEnd"
>
  <Menu.Item :key="" v-for="item in ">
    <Checkbox :value="" @change="menuChange"> {{ item.label }}</Checkbox>
  </Menu.Item>
</Draggable>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

还是刚才那一段代码,再加上这个组件,将list和菜单项的循环数组赋值一样,这样就实现了。
而且这个 回调函数change你可以不做任何处理。页面上的效果已经实现。

如果你需要再拖拽结束后做点什么事情,可以在change事件中做一些处理。

{
    "moved": {
        "element": {
            "label": "半导体",
            "value": "484e1d9a04a711ec8b830242ac110002"
        },
        "oldIndex": 2,
        "newIndex": 3
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

change事件的参数e,参数如上。可以根据以上参数做一些处理。
我这里需要在拖拽后,根据新的位置在对选中的keys值做一次排序。

  const onDragEnd = (e) => {
    // 对 dataSelectedKeys 做一次排序
    const newSelectedKeys = [];
    state.menuItems.forEach((item) => {
      if (state.dataSelectedKeys.includes(item.value)) {
        newSelectedKeys.push(item.value);
      }
    });
    state.dataSelectedKeys = newSelectedKeys;
  };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
'
运行

关于拖拽过程中的样式
ghost-class
chosen-class
drag-class
这些样式需要在开启force-fallback为true并同时css属性important才会生效,目前看效果不好。因为如果开启了force-fallback,就会导致拖拽过程中会出现拖拽过程中鼠标选中移动中的文本元素的现象。这是因为这其实开启了原生html的拖拽行为。
所以不建议。

关于如何禁止某些项目元素不被拖拽或者不被释放(注意类名前.有点):
handle=“.draggable-item” // 禁止在这些元素上释放拖拽
filter=“.nodraggable-item” // 不允许拖拽的元素类名
draggable=“.draggable-item” // 允许拖拽的元素类名

<Menu.Item
   :key=""
   v-for="item in "
   :class="{
     'draggable-item': item.value != 'all' ? true : false,
     'nodraggable-item': item.value === 'all' ? true : false
   }"
 >
   <Checkbox :value="" @change="menuChange"> {{ item.label }}</Checkbox>
 </Menu.Item>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

关于其他属性:

disabled: 经过测试无效(如有测试有效,请联系修改)

属性名称 说明
group 如果一个页面有多个拖拽区域,通过设置group名称可以实现多个区域之间相互拖拽
或者 { name: "...", pull: [true, false, 'clone', array , function], put: [true, false, array , function] }
sort 是否开启排序,如果设置为false,它所在组无法排序
delay 鼠标按下多少秒之后可以拖拽元素
touchStartThreshold 鼠标按下移动多少px才能拖动元素
disabled :disabled= "true",是否启用拖拽组件
animation 拖动时的动画效果,如设置animation=1000表示1秒过渡动画效果
handle :handle=".mover" 只有当鼠标在class为mover类的元素上才能触发拖到事件
filter :filter=".unmover" 设置了unmover样式的元素不允许拖动
draggable :draggable=".item" 样式类为item的元素才能被拖动
ghost-class :ghost-class="ghostClass" 设置拖动元素的占位符类名,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true
chosen-class :ghost-class="hostClass" 被选中目标的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true
drag-class :drag-class="dragClass"拖动元素的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true
force-fallback 默认false,忽略HTML5的拖拽行为,因为h5里有个属性也是可以拖动,你要自定义ghostClass chosenClass dragClass样式时,建议forceFallback设置为true
fallback-class 默认false,克隆选中元素的样式到跟随鼠标的样式
fallback-on-body 默认false,克隆的元素添加到文档的body中
fallback-tolerance 按下鼠标移动多少个像素才能拖动元素,:fallback-tolerance="8"
scroll 默认true,有滚动区域是否允许拖拽
scroll-fn 滚动回调函数
scroll-fensitivity 距离滚动区域多远时,滚动滚动条
scroll-speed 滚动速度