sortablejs 拖拽库

sortablejs 库

列表拖拽
<template>
  <el-scrollbar height="500px">
    <div id="draggableCard">
      <el-card v-for="i in resultDate" :key="i">
        {{ i }}
      </el-card>
    </div>
  </el-scrollbar>
</template>

<script lang="ts" setup>
import {ref,onMounted} from 'vue'
import Sortable from "sortablejs";
const resultDate = ref([1,2,3,4,5]);
onMounted(() => {
  Sortable.create(document.getElementById("draggableCard"), {
    animation: 150,
    onEnd: ({ newIndex, oldIndex }) => {
      const currRow = resultDate.value.splice(oldIndex, 1);
      resultDate.value.splice(newIndex, 0, currRow[0]);
    },
  });
});
</script>
双列表拖拽
<template>
  <div>
    <div class="flex">
      <div class="list" ref="l1">
        {{ list1 }}
        <el-card v-for="(i, index) in list1" :key="i.label">
          {{ index }}-{{ i.label }}
        </el-card>
      </div>
      <div class="list" ref="l2">
        {{ list2 }}
        <el-card v-for="(i, index) in list2" :key="i.label">
          {{ index }}-{{ i.label }}
        </el-card>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import Sortable from "sortablejs";
import { ref, reactive, onMounted } from "vue";
import { cloneDeep } from "lodash";

const list1 = reactive([
  {
    label: "姓名",
    prop: "name",
  },
  {
    label: "性别",
    prop: "gender",
  },
  {
    label: "年龄",
    prop: "age",
  },
  {
    label: "操作",
    prop: "operation",
  },
]);
const list2 = reactive([]);
const l1 = ref();
const l2 = ref();

onMounted(() => {
  sortList();
});

const isMove = ref(true); // 判断是否移动
const sortList = () => {
  Sortable.create(l1.value, {
    group: { name: "card", pull: true, put: true },
    onEnd({ newIndex, oldIndex }) {
      if (isMove.value) {
        const currRow = list1.splice(oldIndex, 1)[0];
        list2.splice(newIndex, 0, currRow);
      } else {
        const currRow = list1.splice(oldIndex, 1)[0];
        list1.splice(newIndex, 0, currRow);
      }
    },
    onUpdate() {
      isMove.value = false;
    },
    onMove() {
      isMove.value = true;
    },
  });
  Sortable.create(l2.value, {
    group: { name: "card", pull: true, put: true },
    onEnd({ newIndex, oldIndex }) {
      if (isMove.value) {
        const currRow = list2.splice(oldIndex, 1)[0];
        list1.splice(newIndex, 0, currRow);
      } else {
        const currRow = list2.splice(oldIndex, 1)[0];
        list2.splice(newIndex, 0, currRow);
      }
    },
    onUpdate() {
      isMove.value = false;
    },
    onMove() {
      isMove.value = true;
    },
  });
};

// targetList 为空 奇怪
const dragOption = (name, currentList, targetList) => {
  return {
    group: { name, pull: true, put: true },
    animation: 150,
    onUpdate() {
      isMove.value = false;
    },
    onMove() {
      isMove.value = true;
    },
    onEnd: ({ newIndex, oldIndex }) => {
      if (isMove.value) {
        const currRow = currentList.splice(oldIndex, 1)[0];
        targetList.splice(newIndex, 0, currRow);
      } else {
        const currRow = currentList.splice(oldIndex, 1)[0];
        currentList.splice(newIndex, 0, currRow);
      }
      console.log("当前列表", currentList);
    },
  };
};
</script>

<style lang="scss" scoped>
.list {
  height: 500px;
  width: 300px;
  border: 1px solid black;
}
</style>
表格拖拽
<template>
    <div class="draggable" style="padding: 20px">
        <el-table
                row-key="id"
                :data="state.tableData"
                style="width: 100%"
        >
            <el-table-column
                    v-for="(item,index) in state.oldList"
                    :key="`col_${index}`"
                    :prop="state.newList[index].prop"
                    :label="item.label"
                    align="center"
            >
            </el-table-column>
        </el-table>
    </div>
</template>
<script setup>
import Sortable from 'sortablejs';
import { reactive, onMounted} from 'vue';

const state = reactive({
    oldList: [],
    newList: [],
    tableData: [
        {
            id:1,
            name:'李四',
            gender:'男',
            age:20,
        },
        {
            id:2,
            name:'王五',
            gender:'未知',
            age:18,
        },
        {
            id:3,
            name:'张三',
            gender:'男',
            age:22,
        },
        {
            id:4,
            name:'张三',
            gender:'男',
            age:22,
        },
    ],
    tableConfig: {
        tableItems: [
            {
                label: '姓名',
                prop: 'name',
            },
            {
                label: '性别',
                prop: 'gender',
            },
            {
                label: '年龄',
                prop: 'age',
            },
        ]
    }
    
})
// 行拖拽
const rowDrop = function () {
    // 要拖拽元素的父容器
    const tbody = document.querySelector('.draggable .el-table__body-wrapper tbody');
    Sortable.create(tbody, {
        //  可被拖拽的子元素
        draggable: ".draggable .el-table__row",
        onEnd({newIndex, oldIndex}) {
            const currRow = state.tableData.splice(oldIndex, 1)[0];
            state.tableData.splice(newIndex, 0, currRow);
            console.log('tableData',state.tableData);
        }
    });
}
// 列拖拽
const columnDrop = function() {
    const wrapperTr = document.querySelector('.draggable .el-table__header-wrapper tr');
    Sortable.create(wrapperTr, {
        animation: 180,
        delay: 0,
        onEnd: evt => {
            const oldItem = state.newList[evt.oldIndex];
            state.newList.splice(evt.oldIndex, 1);
            state.newList.splice(evt.newIndex, 0, oldItem);
        }
    });
}
onMounted(()=> {
    state.oldList = JSON.parse(JSON.stringify(state.tableConfig.tableItems))
    state.newList = JSON.parse(JSON.stringify(state.tableConfig.tableItems))
    columnDrop()
    rowDrop()
})
</script>
表格禁止拖拽到第一行
<template>
    <div class="draggable" style="padding: 20px">
        <el-table
                :row-class-name="rowClassName"
                row-key="id"
                :data="state.tableData"
                style="width: 100%"
        >
            <el-table-column
                    v-for="(item,index) in state.oldList"
                    :key="`col_${index}`"
                    :prop="state.newList[index].prop"
                    :label="item.label"
                    align="center"
            >
            </el-table-column>
        </el-table>
    </div>
</template>
<script setup>
import Sortable from 'sortablejs';
import { reactive, onMounted} from 'vue';

const state = reactive({
    oldList: [],
    newList: [],
    tableData: [
        {
            id:1,
            name:'李四',
            gender:'男',
            age:20,
        },
        {
            id:2,
            name:'王五',
            gender:'未知',
            age:18,
        },
        {
            id:3,
            name:'张三',
            gender:'男',
            age:22,
        },
        {
            id:4,
            name:'张三',
            gender:'男',
            age:22,
        },
    ],
    tableConfig: {
        tableItems: [
            {
                label: '姓名',
                prop: 'name',
            },
            {
                label: '性别',
                prop: 'gender',
            },
            {
                label: '年龄',
                prop: 'age',
            },
        ]
    }
    
})
const rowClassName = ({ row, rowIndex }) => {
    // 为除了第一行外的所有行添加额外样式
    return rowIndex !== 0 ? 'el-table__row__drag' : '';
 }
// 行拖拽
const rowDrop = function () {
    // 要拖拽元素的父容器
    const tbody = document.querySelector('.draggable .el-table__body-wrapper tbody');
    Sortable.create(tbody, {
        //  可被拖拽的子元素
        draggable: ".draggable .el-table__row__drag",    // 修改可拖拽元素
        onEnd({newIndex, oldIndex}) {
            const currRow = state.tableData.splice(oldIndex, 1)[0];
            state.tableData.splice(newIndex, 0, currRow);
            console.log('tableData',state.tableData);
        }
    });
}
// 列拖拽
const columnDrop = function() {
    const wrapperTr = document.querySelector('.draggable .el-table__header-wrapper tr');
    Sortable.create(wrapperTr, {
        animation: 180,
        delay: 0,
        onEnd: evt => {
            const oldItem = state.newList[evt.oldIndex];
            state.newList.splice(evt.oldIndex, 1);
            state.newList.splice(evt.newIndex, 0, oldItem);
        }
    });
}
onMounted(()=> {
    state.oldList = JSON.parse(JSON.stringify(state.tableConfig.tableItems))
    state.newList = JSON.parse(JSON.stringify(state.tableConfig.tableItems))
    columnDrop()
    rowDrop()
})
</script>
穿梭框拖拽
<template>
  <div class="transfer" ref="transfer">
    <el-transfer v-model="value" :data="data" :titles="titles">
      <template #default="{ option }">
        <div class="pannel-content">
          <span :draggable="!option.disabled" @dragstart="drag($event, option)">{{
            option.label
          }}</span>
        </div>
      </template>
    </el-transfer>
  </div>
</template>

<script lang="ts" setup>
import Sortable from "sortablejs";
import { ref, onMounted} from "vue";

const data = ref([
  {
    key: 1,
    label: `身份证取号`,
    disabled: false,
  },
  {
    key: 2,
    label: `人脸取号`,
    disabled: false,
  },
  {
    key: 3,
    label: `亮码取号`,
    disabled: false,
  },
  {
    key: 4,
    label: `人证比对取号`,
    disabled: false,
  },
]);

const titles = ref(["待选列表", "已选列表"]);

const value = ref([] as any);
const draggingKey = ref(null as any);
const transfer = ref<HTMLDivElement | null>(null);
const drag = (ev: DragEvent, option: any) => {
  draggingKey.value = option.key;
};
onMounted(() => {
  const leftPanel = transfer?.value
    ?.getElementsByClassName("el-transfer-panel")[0]
    .getElementsByClassName("el-transfer-panel__body")[0] as any;
  const rightPanel = transfer?.value
    ?.getElementsByClassName("el-transfer-panel")[1]
    .getElementsByClassName("el-transfer-panel__body")[0] as any;
  const leftEl = leftPanel?.getElementsByClassName("el-transfer-panel__list")[0];
  const rightEl = rightPanel?.getElementsByClassName("el-transfer-panel__list")[0];
  Sortable.create(rightEl, {
    onEnd: (evt: any) => {
      const { oldIndex, newIndex } = evt;
      const temp = value.value[oldIndex];
      if (!temp || temp === "undefined") return; // 解决右边最后一项从右边拖左边,有undefined的问题
      value.value[oldIndex] = value.value[newIndex];
      value.value[newIndex] = temp;
    },
  });
  Sortable.create(leftEl, {
    onEnd: (evt: any) => {
      const { oldIndex, newIndex } = evt;
      if (oldIndex === newIndex) return;
      const temp = data.value[oldIndex];
      if (!temp || (temp as any) === "undefined") return; // 解决右边最后一项从右边拖左边,有undefined的问题
      data.value[oldIndex] = data.value[newIndex];
      data.value[newIndex] = temp;
    },
  });
  leftPanel.ondragover = (ev: any) => {
    ev.preventDefault();
  };
  leftPanel.ondrop = (ev: any) => {
    ev.preventDefault();
    const index = value.value.indexOf(draggingKey.value);
    if (index !== -1) {
      value.value.splice(index, 1);
    }
  };
  rightPanel.ondragover = (ev: any) => {
    ev.preventDefault();
  };
  rightPanel.ondrop = (ev: any) => {
    ev.preventDefault();
    if (value.value.indexOf(draggingKey.value) === -1) {
      value.value.push(draggingKey.value);
    }
  };
});
</script>
<style scoped lang="scss">
:deep(.el-transfer__button) {
  width: 30px;
}
</style>
  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值