手写穿梭框

代码仅供参考和学习,写的不是很好,如果哪位大神有更好的编写方式请多多提意见,纠正错误,一起学习。
完整代码:

<template>
  <div class="transfer-child">
    <!-- 左列表 -->
    <div class="transfer-child-left transfer-content">
      <div class="transfer-child-left__header transfer-header">
        <div>
          <label>
            <input
              type="checkbox"
              v-model="leftCheckAll"
              @change="leftCheckedAll"
            />
            列表1
          </label>
        </div>
        <div>{{ count(leftList) }}/{{ leftList.length }}</div>
      </div>
      <div class="transfer-child-search">
        <input
          type="text"
          placeholder="请输入标签名称"
          v-model="lefSearchValue"
        />
      </div>
      <div class="transfer-child-left__list transfer-list">
        <div>
          <div v-for="(lef, index) in lefSearchList" :key="index">
            <label>
              <input
                type="checkbox"
                v-model="lef.check"
                @change="leftCheckChange"
              />
              {{ lef.label }}
            </label>
          </div>
        </div>
      </div>
      <div class="transfer-child-reset">
        <button @click="handleReset">清除</button>
      </div>
    </div>
    <!-- 方向箭头 -->
    <div class="transfer-child-transfer">
      <button
        class="transfer-child-transfer__left"
        :disabled="rigthList.length == 0"
        @click="leftTransfer"
      >
        <img src="./left.png" alt="" height="25" />
      </button>
      <button
        class="transfer-child-transfer__right"
        :disabled="leftList.length == 0"
        @click="rightTransfer"
      >
        <img src="./right.png" alt="" height="25" />
      </button>
    </div>
    <!-- 右列表 -->
    <div class="transfer-child-right transfer-content">
      <div class="transfer-child-right__header transfer-header">
        <div>
          <label>
            <input
              type="checkbox"
              v-model="rightCheckAll"
              @change="rightCheckedAll"
            />
            列表2
          </label>
        </div>
        <div>{{ count(rigthList) }}/{{ rigthList.length }}</div>
      </div>
      <div class="transfer-child-search">
        <input
          type="text"
          placeholder="请输入标签名称"
          v-model="rigSearchValue"
        />
      </div>
      <div class="transfer-child-right__list transfer-list">
        <div v-for="(rig, index) in rigSearchList" :key="index">
          <label>
            <input
              type="checkbox"
              v-model="rig.check"
              @change="rightCheckChange"
            />
            {{ rig.label }}
          </label>
        </div>
      </div>
      <div class="transfer-child-reset">
        <button @click="handleReset">清除</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "transferChild",
  props: {
    value: () => {},
  },
  data() {
    return {
      lefSearchValue: "",
      rigSearchValue: "",
      leftCheckAll: false,
      rightCheckAll: false,
      leftList: [
        { label: "标签1", check: false },
        { label: "标签2", check: false },
        { label: "标签3", check: false },
        { label: "标签4", check: false },
        { label: "标签5", check: false },
        { label: "标签6", check: false },
        { label: "标签7", check: false },
        { label: "标签8", check: false },
      ],
      rigthList: [],
    };
  },
  created() {
    this.leftList.forEach((i, index) => {
      i.sortIndex = index;
      console.log(i);
    });
  },
  computed: {
    lefSearchList() {
      return this.leftList.filter(
        (v) => v.label.indexOf(this.lefSearchValue) !== -1
      );
    },
    rigSearchList() {
      return this.rigthList.filter(
        (v) => v.label.indexOf(this.rigSearchValue) !== -1
      );
    },
  },
  methods: {
    count(data) {
      return data.filter((v) => v.check).length;
    },
    rightTransfer() {
      let selectTags = this.leftList.filter((v) => v.check);
      this.rigthList.push(...selectTags);
      this.leftList = this.leftList.filter((v) => !v.check);
      this.rigthList.sort((a, b) => {
        return a.sortIndex - b.sortIndex;
      });
    },
    leftTransfer() {
      let selectTags = this.rigthList.filter((v) => v.check);
      this.leftList.push(...selectTags);
      this.rigthList = this.rigthList.filter((v) => !v.check);
      this.leftList.sort((a, b) => {
        return a.sortIndex - b.sortIndex;
      });
    },
    leftCheckedAll() {
      this.leftList.forEach((v) => {
        v.check = this.leftCheckAll;
      });
    },
    rightCheckedAll() {
      this.rigthList.forEach((v) => {
        v.check = this.rightCheckAll;
      });
    },
    leftCheckChange() {
      let count = this.leftList.filter((v) => v.check).length;
      // count == this.leftList.length
      //   ? (this.leftCheckAll = true)
      //   : (this.leftCheckAll = false);

      this.leftCheckAll = count == this.leftList.length;
    },
    rightCheckChange() {
      let count = this.rigthList.filter((v) => v.check).length;
      this.rightCheckAll = count == this.rigthList.length;
    },
    handleReset() {
      this.lefSearchValue = "";
      this.rigSearchValue = "";
    },
  },
};
</script>

<style lang="scss">
.transfer-child {
  display: flex;
  // justify-content: center;
  // margin-top: 50px;
  .transfer-content {
    width: 200px;
    height: 300px;
    border: 1px solid #e1e6ed;
    .transfer-header {
      display: flex;
      justify-content: space-between;
      width: 100%;
      height: 45px;
      background-color: #f5f7fa;
      & div {
        line-height: 45px;
        margin: 0 15px;
        font-weight: 400;
      }
      & div:nth-child(2) {
        font-size: 12px;
      }
    }
    .transfer-child-search {
      position: relative;
      text-align: center;
      margin: 15px 0 10px 0;
      & input {
        width: 160px;
        height: 30px;
        border-radius: 20px;
        border: 1px solid #ccc;
        text-align: center;
        font-size: 12px;
        &:focus {
          outline: 1px solid #167fe8;
        }
      }
      &::after {
        position: absolute;
        top: 10px;
        left: 35px;
        content: "";
        display: block;
        width: 15px;
        height: 15px;
        background: url("./search.png");
        background-size: cover;
      }
    }
    .transfer-list {
      width: 186px;
      height: 195px;
      margin-left: 15px;
      overflow: auto;
      & div {
        margin-top: 8px;
      }
    }
    .transfer-child-reset {
      width: 100%;
      height: 40px;
      border: 1px solid #e1e6ed;
      margin: 1px 0 0 -1px;
      text-align: right;
      line-height: 40px;
      & button {
        height: 25px;
        margin-right: 10px;
        background-color: #fff;
        border: 0;
        border-radius: 2px;
        outline: 1px solid #d3dce8;
        &:active {
          outline: 1px solid #409eff;
        }
        &:focus {
          color: #409eff;
          background-color: #d9e8f5;
        }
      }
    }
  }
  .transfer-child-transfer {
    display: flex;
    align-items: center;
    & button {
      width: 56px;
      height: 43px;
      background-color: #409eff;
      border-radius: 5px;
      border: 0;
      outline: 0;
      text-align: center;
      line-height: 55px;
      &:hover {
        background-color: #a0cfff;
      }
    }
    .transfer-child-transfer__left {
      margin-left: 30px;
      margin-right: 10px;
    }
    .transfer-child-transfer__right {
      margin-right: 30px;
    }
  }
}
</style>

功能实现如图:
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值