Vue2 穿梭框组件封装实战:功能增强与灵活扩展

一、引言

        穿梭框(Transfer)是前端开发中常用的组件,用于在两个列表之间移动数据项。虽然 Element UI 提供了基础的 el-transfer 组件,但在实际项目中我们往往需要更丰富的功能和更灵活的定制。本文将详细讲解如何基于 Vue2 和 Element UI 封装一个功能强大的穿梭框组件,并分析其特点、优势及使用方法。

二、先上效果图

三、组件封装详解

想跳过步骤直接使用的,可以直接划到底部看 使用指南 和 完整组件代码.

1. 基础结构搭建

首先我们来看组件的基础模板结构:

<template>
  <div class="transfer">
    <!-- 左框 -->
    <div class="transfer_left" :style="{ width: props.leftWidth }">
      <!-- 左侧内容 -->
    </div>
    
    <!-- 按钮 -->
    <div class="transfer_center">
      <el-button @click="leftClick"></el-button>
      <el-button @click="rightClick"></el-button>
    </div>
    
    <!-- 右框 -->
    <div class="transfer_right" :style="{ width: props.rightWidth }">
      <!-- 右侧内容 -->
    </div>
  </div>
</template>

这个结构创建了一个包含左右两个面板和中间操作按钮的基础布局。通过 props.leftWidthprops.rightWidth 可以动态设置两侧面板的宽度。

2. 数据管理

组件的数据管理是核心功能:

data() {
  return {
    allCheck_left: false, // 左侧全选状态
    allCheck_right: false, // 右侧全选状态

    checked_left: [], // 左侧已选数据
    checked_right: [], // 右侧已选数据

    leftList: [], // 左侧总数据列表
    rightList: [], // 右侧总数据列表

    left_search: "", // 左侧搜索词
    right_search: "" // 右侧搜索词
  };
}

组件通过 data 属性管理所有状态,包括选择状态、数据列表和搜索条件。

这里比较核心的是左右两侧的数据解耦,毕竟我就是为了解决这个问题才封装的这个组件,在element-ui 的 el-transfer 中因左右框共用一套数据的原因,不能在一侧框单独添加检索条件,数据解耦完美的解决了这个问题。

3. 属性配置

组件提供了丰富的配置选项:

props: {
    props: {
      type: Object,
      default() {
        return {
          label: "name", // 显示文本内容字段
          key: "id", // 唯一标识字段
          disabled: "disabled",  // 多选框禁用字段
          leftWidth: "300px", // 左侧宽度
          rightWidth: "300px", // 右侧宽度
        };
      },
    },
    // 源数据
    data: {
      type: Array,
      default() {
        return [];
      },
    },
    // 已选数据
    value: {
      type: Array,
      default() {
        return [];
      },
    },
    // 是否可搜索
    filterable: {
      type: Boolean,
      default() {
        return false;
      },
    },
    // 搜索框提示文字
    filterPlaceholder: {
      type: String,
      default() {
        return "请输入关键字";
      },
    },
    // 两侧标题
    titles: {
      type: Array,
      default() {
        return ["未选数据", "已选数据"];
      },
    },
    // 自定义搜索条件
    search: {
      type: Object,
      default() {
        return {
          left: [],
          right: [],
        };
      },
    },
}

这些属性使得组件可以高度定制化,适应各种业务场景。

为减少学习成本,这里封装的和 el-transfer 相同的属性保持了对齐。

有额外定制需求,也可以在这里继续添加定制化属性。

4. 核心功能实现

数据移动功能
// 将右边选中的数据移动到左边
leftClick() {
  let arr = [];
  this.rightList = this.rightList.filter((item) => {
    if (this.checked_right.includes(item[this.props.key])) {
      this.leftList.push(item);
      arr.push(item);
      return false;
    } else {
      return true;
    }
  });
  this.$emit(
    "change",
    this.rightList.map((item) => item[this.props.key]),
    "left",
    this.checked_right
  );
  this.checked_right = [];
}

// 将左边选中的数据移动到右边
rightClick() {
  let arr = [];
  this.leftList = this.leftList.filter((item) => {
    if (this.checked_left.includes(item[this.props.key])) {
      this.rightList.push(item);
      arr.push(item);
      return false;
    } else {
      return true;
    }
  });
  this.$emit(
    "change",
    this.rightList.map((item) => item[this.props.key]),
    "right",
    this.checked_left
  );
  this.checked_left = [];
}

这两个方法实现了数据在左右面板之间的移动,并在移动后触发 change 事件通知父组件。

搜索过滤功能
computed: {
  // 左边要显示的数据列表
  leftList_bak() {
    let arr = this.leftList.filter((item) =>
      item[this.props.label].includes(this.left_search)
    );
    let array = [arr];
    if (this.search.left && this.search.left.length) {
      array.push(...th
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值