vue3+ts树形穿梭框

631 阅读1分钟
<template>
  <div class="flex flex-wrap">
    <div class="m-4 SelectBox">
      <div class="boxCenter">
        <el-tree ref="leftTreeRef" :data="leftData" :props="defaultProps" show-checkbox node-key="id" />
      </div>
    </div>

    <div class="m-4 transferBtn">
      <div class="pickBtn" @click="towardsRight">&gt;&gt;</div>
      <div class="pickBtn" @click="towardsLeft">&lt;&lt;</div>
    </div>

    <div class="m-4 SelectBox">
      <div class="boxCenter">
        <el-tree ref="rightTreeRef" :data="rightData" :props="defaultProps" show-checkbox node-key="id" />
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import type { ElTree } from 'element-plus';

interface TreeNode {
  id: string;
  label: string;
  pid?: string;
  children?: TreeNode[];
}
interface CopyNodes {
  id: string;
  label: string;
  pid: string;
  children?: TreeNode[]
}
const mockTreeData: TreeNode[] = [
  {
    id: '1',
    label: '1',
    children: [
      {
        id: '1-1',
        label: '1-1',
        pid: '1',
      },
      {
        id: '1-2',
        label: '1-2',
        pid: '1',
      },
      {
        id: '1-3',
        label: '1-3',
        pid: '1',
      },
    ],
  },
  {
    id: '2',
    label: '2',
    children: [
      {
        id: '2-1',
        label: '2-1',
        pid: '2',
      },
      {
        id: '2-2',
        label: '2-2',
        pid: '2',
      },
      {
        id: '2-3',
        label: '2-3',
        pid: '2',
      },
    ],
  },
  {
    id: '3',
    label: '3',
    children: [
      {
        id: '3-1',
        label: '3-1',
        pid: '3',
      },
      {
        id: '3-2',
        label: '3-2',
        pid: '3',
      },
      {
        id: '3-3',
        label: '3-3',
        pid: '3',
      },
    ],
  },
];
const defaultProps = {
  children: 'children',
  label: 'label',
};

const leftData = ref<TreeNode[]>(mockTreeData);
const rightData = ref<TreeNode[]>([]);
const leftTreeRef = ref<InstanceType<typeof ElTree>>()
const rightTreeRef = ref<InstanceType<typeof ElTree>>()
const towardsRight = () => {
  const checkedNodes = leftTreeRef.value!.getCheckedNodes(false, true);
  const checkedKeys = leftTreeRef.value!.getCheckedKeys(false);

  const copyNodes = JSON.parse(JSON.stringify(checkedNodes));
  copyNodes.forEach((x: CopyNodes) => {
    x.children = [];
    if (!rightTreeRef.value!.getNode(x.id)) {
      rightTreeRef.value!.append(x, x.pid);
    }
  });

  checkedKeys.forEach((x: any) => {
    leftTreeRef.value!.remove(x);
  });

  afterToward();
};

const towardsLeft = () => {
  const checkedNodes = rightTreeRef.value!.getCheckedNodes(false, true);
  const checkedKeys = rightTreeRef.value!.getCheckedKeys(false);

  const copyNodes = JSON.parse(JSON.stringify(checkedNodes));
  copyNodes.forEach((x: CopyNodes) => {
    x.children = [];
    if (!leftTreeRef.value!.getNode(x.id)) {
      leftTreeRef.value!.append(x, x.pid);
    }
  });

  checkedKeys.forEach((x: any) => {
    rightTreeRef.value!.remove(x);
  });

  afterToward();
};
const afterToward = () => {
  leftTreeRef.value!.setCheckedKeys([]);
  rightTreeRef.value!.setCheckedKeys([]);
  console.log(leftData.value, rightData.value);
};

</script>

<style scoped lang="less">
.flex {
  display: flex;
}

.m-4 {
  margin: 1rem;
}

.SelectBox {
  border: 1px solid #ccc;
  height: 270px;
  width: 200px;
  color: #fff;
  position: relative;

  .boxTitle {
    background: #a0cfff;
    height: 30px;
    line-height: 30px;
    text-align: center;
    border-bottom: 1px solid #ccc;
    cursor: pointer;
  }

  .boxCenter {
    height: 100%;
    width: 100%;
    max-height: 239px;
    overflow-y: scroll;
  }
}

.transferBtn {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;

  .pickBtn {
    height: 30px;
    width: 50px;
    background: #a0cfff;
    color: #fff;
    font-weight: 700;
    font-size: 20px;
    border-radius: 5px;
    margin-top: 10px;
    text-align: center;
    line-height: 30px;
    cursor: pointer;
  }
}
</style>

根据blog.csdn.net/github_3563…改造