# Transfer 穿梭框

- 来源：[E10 UI 组件库](https://www.e-cology.com.cn/ui/transfer/freepass)
- 平台：PC
- 维护者：赵俊飞
- 设计稿：http://pd.e-cology.com.cn/pd/E10/interface/e10xiaoguotu/PC/zms/daibanliucheng/#s13
- Issue：http://gitlab.ecology10.cn/FRONTEND/weapp-ui/-/issues?state=all&search=[Tree]

## 代码演示

### 基础用法

直接引入组件进行使用

```jsx
import React, { PureComponent } from 'react'
import { Transfer, transferData, ListProps } from "@weapp/ui"
export default class Basic extends PureComponent {

  onSelect = (selectedKeys: string[], selectedData: transferData) => {
    console.log(selectedKeys, selectedData);
  }

  onAfterDeleteAll = (selectedKeys: string[], deletedData: transferData) => {
    console.log(selectedKeys, deletedData)
  }

  render() {
    let dataSource: transferData[] = [];
    const selectedKeys = ['1', '2'];
    for (let i = 0; i <=20; i++) {
      dataSource.push({ id: i.toString(), title: `content${i}` })
    }
    return <div style={{ width: '500px',height:'300px' }}>
      <Transfer onSelect={this.onSelect} onAfterDeleteAll={this.onAfterDeleteAll} selectedKeys={selectedKeys} dataSource={dataSource} />
    </div>
  }
}
```

### 受控

选中受控

```jsx
import React, { PureComponent } from 'react';
import { Transfer, transferData, Dialog} from "@weapp/ui";
import { getLabel } from '@weapp/utils';

const { confirm } = Dialog;
export default class Basic extends PureComponent {
  state = {
    value: ['4']
  }

  onSelect = (selectedKeys: string[], selectedData: transferData) => {
    console.log(selectedKeys, selectedData);
    this.setState({
      value: selectedKeys
    });
  }

  onDelete = (selectedKeys: string[], removedData: transferData) => {
    console.log(selectedKeys, removedData);
    this.setState({ value: selectedKeys });
  }

  onDeleteAll = (selectedKeys: string[], deletedData: transferData) => {
    confirm({
      content: getLabel('12764','确定要删除吗') ,
      onOk:()=>{
        this.setState({value:selectedKeys})
      }
    })
    console.log(selectedKeys, deletedData)
  }

  onAfterDeleteAll = (selectedKeys: string[], deletedData: transferData) => {
    console.log(selectedKeys, deletedData)
  }

  render() {
    const { value } = this.state;
    const selectedKeys = ['1', '2'];
    let dataSource: transferData[] = [];
    for (let i = 0; i < 5; i++) {
      dataSource.push({ id: i.toString(), title: `content${i}` })
    }
    return <div style={{ width: '500px' }}>
      <Transfer value={value} onSelect={this.onSelect} onDelete={this.onDelete} onDeleteAll={this.onDeleteAll}
       onAfterDeleteAll={this.onAfterDeleteAll} dataSource={dataSource} selectedKeys={selectedKeys} />
    </div>
  }
}
```

### 自定义渲染content

通过customRenderLeftContent和customRenderRightContent自定义渲染content

```jsx
import React, { PureComponent } from 'react'
import { Transfer, transferData, } from "@weapp/ui"

export default class Basic extends PureComponent {

  onSelect = (selectedKeys: string[], selectedData: transferData) => {
    console.log(selectedKeys, selectedData);
  }

  customRenderRightContent = (rowData: transferData, index: number) => {
    return <div>
      {`右侧自定义渲染${rowData.title}`}
    </div>
  }

  customRenderLeftContent = (rowData: transferData, index: number) => {
    return <div>
      {`左侧自定义渲染${rowData.title}`}
    </div>
  }

  render() {
    let dataSource: transferData[] = [];
    const selectedKeys = ['1', '2'];
    for (let i = 0; i < 5; i++) {
      dataSource.push({ id: i.toString(), title: `content${i}` })
    }
    return <div style={{ width: '500px' }}>
      <Transfer onSelect={this.onSelect} selectedKeys={selectedKeys} customRenderLeftContent={this.customRenderLeftContent} customRenderRightContent={this.customRenderRightContent} dataSource={dataSource} />
    </div>
  }
}
```

### 自定义渲染全选行

通过customRenderCheckoutAllContent和customRenderCheckoutAllText自定义渲染全选行或全选行的文字

```jsx
import React, { PureComponent } from 'react'
import { Transfer, transferData } from "@weapp/ui"

export default class Basic extends PureComponent {

  onSelect = (selectedKeys: string[], selectedData: transferData) => {
    console.log(selectedKeys, selectedData);
  }

  customRenderCheckAllContent = () => {
    return <div>
      <span style={{ fontSize: '20px' }}>Checked All</span> <span style={{ color: '#aaa' }}>选中所有的数据 </span>
    </div>
  }

  render() {
    let dataSource: transferData[] = [];
    const selectedKeys = ['1', '2'];
    for (let i = 0; i < 5; i++) {
      dataSource.push({ id: i.toString(), title: `content${i}` })
    }
    return <div style={{ width: '500px' }}>
      <h3>自定义渲染全选行的文字</h3>
      <Transfer onSelect={this.onSelect} customRenderCheckAllText={'全选'} selectedKeys={selectedKeys} dataSource={dataSource} />
      <br />
      <h3>自定义渲染全选行</h3>
      <Transfer onSelect={this.onSelect} customRenderCheckAllContent={this.customRenderCheckAllContent} selectedKeys={selectedKeys} dataSource={dataSource} />
    </div>
  }
}
```

### 使用栅格布局配置左右宽度

通过span属性配置

```jsx
import React, { PureComponent } from 'react'
import { Transfer, transferData } from "@weapp/ui"

export default class Basic extends PureComponent {

  onSelect = (selectedKeys: string[], selectedData: transferData) => {
    console.log(selectedKeys, selectedData);
  }

  render() {
    let dataSource: transferData[] = [];
    const selectedKeys = ['1', '2'];
    for (let i = 0; i < 5; i++) {
      dataSource.push({ id: i.toString(), title: `content${i}` })
    }
    return <div style={{ width: '500px' }}>
      <Transfer onSelect={this.onSelect} span={[13, 11]} selectedKeys={selectedKeys} dataSource={dataSource} />
    </div>
  }
}
```

### 已选数据支持拖动排序

```jsx
import React, { PureComponent } from 'react'
import { Transfer, transferData } from "@weapp/ui"

export default class Basic extends PureComponent {

  onSelect = (selectedKeys: string[], selectedData: transferData) => {
    console.log(selectedKeys, selectedData);
  }

  onAfterDeleteAll = (selectedKeys: string[], deletedData: transferData) => {
    console.log(selectedKeys, deletedData)
  }

  onSortEnd = (data: Record<string, unknown>[]) => {
    console.log('拖动后的数据', data);
  }

  render() {
    let dataSource: transferData[] = [];
    const selectedKeys = ['1', '2'];
    for (let i = 0; i <=20; i++) {
      dataSource.push({ id: i.toString(), title: `content${i}` })
    }

    return <div style={{ width: '500px', height: '300px' }}>
      <Transfer
       
        sortable
        selectedKeys={selectedKeys}
        dataSource={dataSource}
        onSelect={this.onSelect}
        onSortEnd={this.onSortEnd}
        onAfterDeleteAll={this.onAfterDeleteAll} />
    </div>
  }
}
```

## 注意

```typescript
1.原版穿梭框右侧移除事件为直接清空所有选项，对应的回调函数为onDeleteAll与onAfterDeleteAll事件
2.新版穿梭框新增了可以选中右侧数据的功能，移除栏只有在有选中数据的时候才会出现，移除事件替换为移除右侧已选中的数据，对应的回调函数为onDeleteRightOptions与onAfterDeleteRightOptions
3.新版交互上线以后，旧版本的两个回掉函数废弃，且使用时不会有ts警告
```

## API

### 参数说明如下：

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
| --- | --- | --- | --- | --- |
| dataSource | 数据源 | transferData | 是 |  |
| selectedKeys | 选中的项 | string[] | 否 |  |
| value | 选中受控 | string[] | 否 |  |
| span | 栅格布局 | Number[] | 否 | [12,12] |
| leftPlaceHolder | 左侧 input 的 placeholder | string | 否 | 请输入关键词 |
| rightPlaceHolder | 右侧 input 的 placeholder | string | 否 | 请输入关键词 |
| leftListProps | 传递给左侧 List 的属性 | ListProps | 否 |  |
| rightListProps | 传递给右侧 List 的属性 | ListProps | 否 |  |
| onSelect | onselect 事件 | (selectedKeys: string[], selectedData: transferData) => void | 否 |  |
| onDelete | 删除事件 | (selectedKeys: string[], removeData: transferData) => void | 否 |  |
| onDeleteAll | 清空右侧所有数据（交互调整后该方法已经废弃） | (selectedKeys: string[], removeData: transferData) => void | 否 |  |
| onAfterDeleteAll | 清空右侧所有数据的 after 事件（交互调整后该方法已经废弃） | (selectedKeys: string[], removeData: transferData) => void | 否 |  |
| onDeleteRightOptions | 移除右侧选中数据回调 | (selectedKeys: string[], removeData: transferData) => void | 否 |  |
| onAfterDeleteRightOptions | 移除右侧选中数据回调的 after 事件 | (selectedKeys: string[], removeData: transferData) => void | 否 |  |
| customRenderRightContent | 右侧自定义渲染 | (rowData: transferData \| transferData[], rowIndex: number) => ReactNode | 否 |  |
| customRenderLeftContent | 左侧自定义渲染 | (rowData: transferData \| transferData[], rowIndex: number) => ReactNode; | 否 |  |
| customRenderCheckAllText | 自定义渲染全选行的文字 | (() => ReactNode) \| ReactNode | 否 |  |
| customRenderCheckAllContent | 自定义渲染全选行 | (() => ReactNode) \| ReactNode | 否 |  |
| customCheckAllChange | 自定义全选事件 | (checked: boolean, selectedKeys: string[], selectedData: transferData) | 否 |  |
| onSortEnd | 已选数据拖动事件回调 | (data: transferData[]) => void | 否 |  |
| sortable | 已选数据是否可拖动排序 | boolean | 否 | false |
| onLeftSearchChange | 左侧输入框change事件 | (value: ReactText)=> void | 否 |  |
| onRightSearchChange | 右侧输入框change事件 | (value: ReactText)=> void | 否 |  |
| sortByOrigin | 已选数据按照左侧列表排序 | boolean | 否 | true |
| sortByValue | 已选数据按照value值排序 | boolean | 否 | false |
