vue.draggable.next group 分组拖拽

vue.draggable.next 的 group 属性可以实现分组拖拽,比如A和B区间相互拖拽,也可以实现A允许拖入B,但是B不允许拖入A区域。

group属性

//方式一:字符串
group:'itxst' //直接设置组名称

//方式二:object
group:{
    name:'itxst',//分组名称itxst的组之间可以相互拖拽
    pull:true|false|function,//是否允许拖入当前组
    put:true|false|function,//是否允许拖出当前组
}

设置分组名称

// 不同的组设置了相同的组名称就可以相互拖拽了
<draggable group="group1" />

控制拖入拖出

//group 属性也可以是对象
<draggable  :group="groupA" />
<script setup> 
const state = reactive({ 
    groupA:{
      name:'itxst',
      pull:true,//允许拖出,如果设置 字符串'clone' 表示该组拖出的元素会被克隆
      put:true  //允许拖入
    } 
});
</script>

自定义函数

// group 属性也可以是对象
<draggable  :group="state.groupA" />
<script setup> 
const state = reactive({ 
    groupA:{
      name:'itxst',
      put:true,
      pull:()=>{
          //当A组元素小于等于3个时,不允许再拖出元素了
          return state.modules.arr1.length>3;
       }
    } 
});
</script>

在线试一试

<template>
  <div class="msg">{{ state.message }}</div>
  <div class="itxst">
    <div class="group">
      <draggable
        :list="state.modules.arr1"
        ghost-class="ghost"
        handle=".move"
        filter=".forbid"
        :force-fallback="true"
        chosen-class="chosenClass"
        animation="300"
        @start="onStart"
        @end="onEnd"
        :group="state.groupA"
        :fallback-class="true"
        :fallback-on-body="true"
        :touch-start-threshold="50"
        :fallback-tolerance="50"
        :move="onMove"
        :sort="false"
      >
        <template #item="{ element }">
          <div class="item move">
            <label class="move">{{ element.name }}</label>
            <span
              v-html="element.name == '消息' ? 'www.itxst.com' : '内容....'"
            ></span>
          </div>
        </template>
      </draggable>
    </div>
    <div class="group">
      <draggable
        :list="state.modules.arr2"
        ghost-class="ghost"
        handle=".move"
        filter=".forbid"
        :force-fallback="true"
        chosen-class="chosenClass"
        animation="300"
        @start="onStart"
        @end="onEnd"
        group="itxst"
        :fallback-class="true"
        :fallback-on-body="true"
        :touch-start-threshold="50"
        :fallback-tolerance="50"
        :move="onMove"
      >
        <template #item="{ element }">
          <div class="item move">
            <label class="move">{{ element.name }}</label>
            <span>内容....</span>
          </div>
        </template>
      </draggable>
    </div>
  </div>
</template>
<script setup>
import { ref, reactive } from "vue";
//导入draggable组件
import draggable from "vuedraggable";

const state = reactive({
  message: "A组只能往B组拖到一个元素",
  groupA: {
    name: "itxst",
    put: true, //允许拖入
    pull: () => {
      let res = state.modules.arr1.length > 3;
      //当A组元素小于等于3个时,不允许再拖出元素了
      state.message = res ? "只能拖出1个" : "不能再拖了";
      return res;
    },
  },
  modules: {
    arr1: [
      { name: "A组", id: 1 },
      { name: "库存", id: 2 },
      { name: "销量", id: 3 },
      { name: "日志", id: 4 },
    ],
    arr2: [
      { name: "B组", id: 5 },
      { name: "员工", id: 6 },
      { name: "报表", id: 7 },
    ],
  },
});

//拖拽开始的事件
const onStart = () => {
  console.log("开始拖拽");
};

//拖拽结束的事件
const onEnd = () => {
  console.log("结束拖拽");
};

const onMove = (e, originalEvent) => {
  //不允许停靠
  if (e.relatedContext.element.disabledPark == true) return false;

  return true;
};
</script>
<style >
body {
  padding: 0px;
  margin: 0px;
  background-color: #f1f1f1;
}
.msg {
  padding: 10px 20px 0px 20px;
}
.itxst {
  background-color: #f1f1f1;
  display: flex;
  padding: 20px;
}

.group {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-content: center;
  width: 32%;
  margin-right: 20px;
}
.item {
  border: solid 1px #ddd;
  padding: 0px;
  text-align: left;
  background-color: #fff;
  margin-bottom: 10px;
  display: flex;
  height: 36px;
  user-select: none;
}

.item > label {
  padding: 6px 10px;
  color: #333;
}
.item > label:hover {
  cursor: move;
}
.item > span {
  padding: 6px 10px;
  color: #666;
}
.ghost {
  border: solid 1px rgb(19, 41, 239) !important;
}
.chosenClass {
  opacity: 1;
  border: solid 1px red;
}
.fallbackClass {
  background-color: aquamarine;
}
</style>