# TableTransfer 表格穿梭框

版本:1.14.0

开发:张鑫14

# 安装

$ npm i @hui-pro/table-transfer -D
# 或者
$ yarn add @hui-pro/table-transfer --dev

# 引入

import tableTransfer from '@hui-pro/table-transfer';
import '@hui-pro/table-transfer/theme/index.scss';
Vue.use(tableTransfer);

# 表格内容穿梭

待添加 (0/500)


已添加 (0/2)

表格内容穿梭
<template>
  <div style="height:522px;">
    <h-table-transfer
      ref="tableTransfer"
      :left-table-data="leftData"
      :right-table-data="rightData"
      tree-node-id="root"
      row-key="id"
      :name-key="['label', 'description']"
      :load-num="50"
    >
      <el-button slot="leftAddition" type="link" style="float: right">
        额外按钮
      </el-button>
      <el-button slot="rightAddition" type="link" style="float: right">
        额外按钮
      </el-button>
      <template slot="leftTableColumn">
        <el-table-column
          label="label"
          prop="label"
          show-overflow-title
        ></el-table-column>
        <el-table-column
          label="description"
          prop="description"
          show-overflow-title
        ></el-table-column>
        <el-table-column prop="description" label="主体编号">
          <template slot-scope="scope">
            <i class="h-icon-circle_info"></i>
          </template>
        </el-table-column>
      </template>
      <template slot="rightTableColumn">
        <el-table-column
          label="label"
          prop="label"
          show-overflow-title
        ></el-table-column>
        <el-table-column
          label="description"
          prop="description"
          show-overflow-title
        ></el-table-column>
      </template>
    </h-table-transfer>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        leftData: [],
        rightData: [
          {
            id: '1-1',
            label: '4-base',
            belongArea: 'root',
            description: 'System Manager'
          },
          {
            id: '2-1',
            label: '5-System',
            belongArea: 'root',
            description: 'System Manager'
          }
        ],
        tableTreeLeft: [],
        tableTreeRight: []
      };
    },

    created() {
      for (let i = 0; i < 500; i++) {
        this.bigTestData.push({
          id: i,
          label: `${i}-System`,
          belongArea: 'root',
          description: `System Manager ${i}`
        });
      }
    },

    mounted() {
      this.leftData = this.bigTestData;
    }
  };
</script>

# 表格内容穿梭,搜索区域自定义

待添加 (0/500)


已添加 (0/2)

表格内容穿梭,搜索区域自定义
<template>
  <div style="height:522px;">
    <h-table-transfer
      ref="tableTransfer"
      :left-table-data="leftData"
      :right-table-data="rightData"
      :left-filter-handler="leftFilterHandler"
      :right-filter-handler="rightFilterHandler"
      tree-node-id="root"
      row-key="id"
      :name-key="['label', 'description']"
      :is-show-check-box="true"
      :load-num="50"
    >
      <template slot="leftSearchBar" slot-scope="scope">
        <el-input
          placeholder="请输入内容"
          v-model="leftTableSearchKeyword"
          :on-icon-click="scope.leftFilter"
          @keyup.enter.native="scope.leftFilter"
          :clear-icon-click="scope.leftClearFilter"
          clearable
          suffix-icon="h-icon-search"
        >
          <el-select
            style="width: 120px"
            v-model="leftTableSearchType"
            slot="prepend"
            placeholder="请选择"
          >
            <el-option label="label" value="1"></el-option>
            <el-option label="description" value="2"></el-option>
          </el-select>
        </el-input>
      </template>
      <template slot="leftTableColumn">
        <el-table-column
          label="label"
          prop="label"
          :show-overflow-title="true"
        ></el-table-column>
        <el-table-column
          label="description"
          prop="description"
          :show-overflow-title="true"
        ></el-table-column>
        <el-table-column prop="description" label="主体编号">
          <template slot-scope="scope">
            <i class="h-icon-circle_info"></i>
          </template>
        </el-table-column>
      </template>
      <template slot="rightSearchBar" slot-scope="scope">
        <el-input
          placeholder="请输入内容"
          v-model="rightTableSearchKeyword"
          :on-icon-click="scope.rightFilter"
          @keyup.enter.native="scope.rightFilter"
          :clear-icon-click="scope.rightClearFilter"
          clearable
          suffix-icon="h-icon-search"
        >
          <el-select
            style="width: 120px"
            v-model="rightTableSearchType"
            slot="prepend"
            placeholder="请选择"
          >
            <el-option label="label" value="1"></el-option>
            <el-option label="description" value="2"></el-option>
          </el-select>
        </el-input>
      </template>
      <template slot="rightTableColumn">
        <el-table-column
          label="label"
          prop="label"
          :show-overflow-title="true"
        ></el-table-column>
        <el-table-column
          label="description"
          prop="description"
          :show-overflow-title="true"
        ></el-table-column>
      </template>
    </h-table-transfer>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        leftData: [],
        rightData: [
          {
            id: '1-1',
            label: '4-base',
            belongArea: 'root',
            description: 'System Manager'
          },
          {
            id: '2-1',
            label: '5-System',
            belongArea: 'root',
            description: 'System Manager'
          }
        ],
        tableTreeLeft: [],
        tableTreeRight: [],
        leftTableSearchKeyword: '',
        leftTableSearchType: '1',
        rightTableSearchKeyword: '',
        rightTableSearchType: '1'
      };
    },

    created() {
      for (let i = 0; i < 500; i++) {
        this.bigTestData.push({
          id: i,
          label: `${i}-System`,
          belongArea: 'root',
          description: `System Manager ${i}`
        });
      }
    },

    mounted() {
      this.leftData = this.bigTestData;
    },
    methods: {
      // 穿梭框中左侧搜索表格数据的处理方法
      leftFilterHandler(item) {
        if (this.leftTableSearchType === '1') {
          return item.label.includes(this.leftTableSearchKeyword);
        }
        if (this.leftTableSearchType === '2') {
          return item.description.includes(this.leftTableSearchKeyword);
        }
      },
      // 穿梭框中右侧搜索表格数据的处理方法
      rightFilterHandler(item) {
        if (this.rightTableSearchType === '1') {
          return item.label.includes(this.rightTableSearchKeyword);
        }
        if (this.rightTableSearchType === '2') {
          return item.description.includes(this.rightTableSearchKeyword);
        }
      }
    }
  };
</script>

# 树表格内容穿梭

待添加 (0/200)


已添加 (0/0)

自定义无数据展示

树表格内容穿梭
<template>
  <div style="height:522px;">
    <h-table-transfer
      ref="tableTransfer"
      :left-table-data="tableTreeLeft"
      :right-table-data="tableTreeRight"
      row-key="indexCode"
      parent-key="parentIndexCode"
      :name-key="['label', 'parentLabel']"
      tree-node-id="root"
      :is-table-tree="true"
      :is-show-check-box="true"
      :load-num="20"
    >
      <template slot="leftTableColumn">
        <h-table-tree-column
          prop="label"
          label="label"
          tree-key="indexCode"
          parent-key="parentIndexCode"
          :expand-on-click-node="false"
          :show-overflow-title="true"
          class-name="test"
        ></h-table-tree-column>
        <el-table-column
          label="description"
          prop="description"
          :show-overflow-title="true"
        ></el-table-column>
      </template>
      <template slot="rightTableColumn">
        <el-table-column
          label="label"
          prop="label"
          :show-overflow-title="true"
        ></el-table-column>
        <el-table-column
          label="description"
          prop="description"
          :show-overflow-title="true"
        ></el-table-column>
      </template>
      <template slot="empty">
        <p>自定义无数据展示</p>
      </template>
    </h-table-transfer>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        tableTreeLeft: []
      };
    },

    created() {
      for (let i = 0; i < 100; i++) {
        this.bigTestData2.push({
          indexCode: `${i}`,
          parentIndexCode: 'root',
          leaf: false,
          parentLabel: `${i}-System-${i}`,
          label: `${i}-System-${i}`,
          description: `System Manager ${i}`
        });
      }
      this.bigTestData2.forEach((item, index) => {
        for (let j = 0; j < 2; j++) {
          this.bigTestData2.push({
            indexCode: `${index}-${j}`,
            parentIndexCode: `${index}`,
            leaf: true,
            parentLabel: `${index}-System-${index}`,
            label: `${index}-${j}-System`,
            description: `System Manager ${index}-${j}`
          });
        }
      });
    },

    mounted() {
      this.tableTreeLeft = bigTestData2;
    }
  };
</script>

# 常见问题

1. 从左侧移到右侧没有问题,但是从左侧移到右侧报错。

  1. 左侧存在组织树或者区域树时,穿梭框从左侧移到右侧时,内部会通过 belongArea(没有设置 belongField 的情况下)判断移动的节点是否属于当前左侧树选中的组织或者区域,如果属于才会显示在右侧的列表中,不属于的会移过去,但是不会显示。

  2. 右侧节点数据中需要包含该节点所属的区域或者组织的数组(一般情况下是节点的 id)

2. 需求中有包含下级的功能,在勾选包含下级的情况下,右侧数据移到左侧时,左侧没有显示移动的节点。

在这种情况下,右侧列表的数据中的所属组织或者区域的字段需要是一个包含该节点的所有父节点的数组,这样向左移动时,只要是移动节点中的所属组织或者区域的数据包含当前选中的组织或者区域,那么都能移过去并且显示。

3. 什么情况下不需要传入belongArea

如果只是单个穿梭框的情况下(没有回显的需求),可以不传入该字段。控件内部会默认将treeNodeId字段作为该字段的值。所以treeNodeId是必传字段,但是对具体的值没有什么要求。

4. 直接修改leftTableDaterightTableData值为什么没有生效。

为了不受对象引用造成影响,控件内部在接收到上面两个参数之后,会完全拷贝一份,所以如果想修改这两个参数需要重新赋值。不推荐利用对象的引用关系直接修改数据,这样会使数据的变化变的很难跟踪。

5. 为什么要前端做搜索。可以改成后台搜索吗?

控件中的一些交互,比如:全选,移到左侧之后,右侧需要消失等交互,如果是后台搜素就无法实现。

如果存在真的数据量特别大的情况时,可以改成后台搜索,但是会存在一定限制。下面是海豚中使用的折中方式:

  • 后台永远只返回给前端 前 1000 条数据,用户可以通过精确搜索来获得其它想要的数据
  • 搜索由在前端搜索改为在后台搜索(因为前端仅能在获得的所有数据中搜);
  • 穿梭框右侧数据超过 1000 条时,就不能再执行从左往右穿梭的操作(但是可以从右往左穿回来)。换句话说,每次仅能保存至多 1999 条数据,如果有 2000 条数据,需要保存后重新进入页面执行第二次操作。

# TableTransfer 参数

参数 说明 类型 可选值 默认值
is-table-tree 用于标记是否是表格树 Boolean true/false false
load-num 一页展示展示的条数(能避免页面一次性渲染大量DOM的问题,但是数据量过大导致的性能的问题还是无法避免) Number 1000
big-data-mode 是否是大数据模式,这个适用于数据量非常大的业务场景,开启之后,已选数量和总数会被影藏掉,数据总条数可以自定义,配合后台搜索,来避免数据量过大,页面卡死的情况 Boolean false
left-table-data 左侧表格数据 Array []
right-table-data 右侧表格数据 Array []
tree-node-id 如果穿梭框左侧还有树,该字段用于描述列表中的根节点与左侧树的父子关系 String
row-key 每一条数据唯一id的key String id
btn-type 左右移按钮的大小,small对应的按钮宽度是32px;normal对应的按钮宽度是40px;big对应的按钮宽度是48px;text对应的是按钮有文字显示; String small/normal/big/text normal
parent-key 父节点Id的key String pId
name-key 搜索名称的key,传入array时,支持多列内容搜索。注意:array的第一个值或string必须为列表的第一列的prop String, Array
cache-right-data 右侧列表作为独立的数据源,与左侧表格选中无关,只和外部传入有关 Boolean true
is-show-check-box 是否显示左侧表格右上角checkbox Boolean false
check-text 左侧表格右上角checkbox的文字信息 String 包含下级人员
belong-field 节点所属组织(区域)的字段,右侧列表如果有回显的数据时,需要配置该字段 String belongArea
left-table-title 待添加表格标题 String 待添加
left-table-input-ph 待添加表格搜索的placeholder String 搜索...
left-table-loading-text 待添加表格loading文字 String 正在加载数据...
left-table-empty-text 待添加表格数据为空时显示的文字 String 暂无数据
right-table-title 已添加表格标题 String 已添加
right-table-input-ph 已添加表格搜索的placeholder String 搜索...
right-table-empty-text 已添加表格数据为空时显示的文字 String 请选择需要添加的数据
left-filter-handler 左侧使用自定义搜索区域时,过滤规则,参数为列表中的一项数据对象 Function 内置默认过滤规则
right-filter-handler 右侧使用自定义搜索区域时,过滤规则,参数为列表中的一项数据对象 Function 内置默认过滤规则
move-right-action 当数据向右侧移动时,触发的事件,该方法需要返回一个promise,resolve时继续右移操作,reject时终止操作 checkedRows, leftTableData, rightTableData
move-left-action 当数据向左侧移动时,触发的事件,该方法需要返回一个promise,resolve时继续左移操作,reject时终止操作 moveLeftData, leftTableData, rightTableData

# TableTransfer 事件

参数 说明 返回值
check-changed 左侧表格右上角checkbox勾选发生变化时触发 value, event
right-table-filter-change 当左侧表格的筛选条件发生变化的时候会触发该事件,参数的值是一个对象,对象的 key 是 column 的 columnKey,对应的 value 为用户选择的筛选条件的数组。 value, event
right-table-filter-change 当右侧表格的筛选条件发生变化的时候会触发该事件,参数的值是一个对象,对象的 key 是 column 的 columnKey,对应的 value 为用户选择的筛选条件的数组。 value, event
move-right 点击右移按钮时触发 leftTableData, rightTableData
move-left 点击左移按钮时触发 leftTableData, rightTableData
left-table-sort-change 当左侧表格的排序条件发生变化的时候会触发该事件 value, { column, prop, order }
right-table-sort-change 当右侧表格的排序条件发生变化的时候会触发该事件 value, { column, prop, order }
expand-click 树表格父节点展开收起触发的事件 expanded, row

# TableTransfer ref 事件

参数 说明 返回值
getCacheData 用于获取左右列表的数据 {leftTableCacheData, rightTableCacheData}