antd中在vue项目中自定义穿梭框
1、完成代码
<template><a-modaltitle="高危因素选择":width="1000":visible="riskVisible":confirm-loading="confirmLoading"@ok="handleOk"@cancel="handleCancel"okText="确认"><a-transferclass="tree-transfer":data-source="dataSource":target-keys="targetKeys":render="item => item.title":show-select-all="false"@change="onChange":titles="['可选择高危因素', '已选中高危因素']"><templateslot="children"slot-scope="{ props: { direction, selectedKeys }, on: { itemSelect } }"><div v-if="direction === 'left'"><div class="nav-list"><div v-for="(item, index) in navList":key="index"@click="handleNavChange(index)":class="['nav-item', currentNav === index ? 'current-color' : '']">{{item.title}}</div></div><div class="left-ipt"><a-input placeholder="搜索可选择内容"><a-icon slot="prefix" type="search"></a-icon></a-input><a-button type="primary" class="search-btn">搜索</a-button></div><a-treev-if='treeData.length':showLine="showLine"blockNodecheckablecheckStrictly:tree-data="renderTreeData":defaultExpandedKeys="['1', '2']":checkedKeys="[...selectedKeys, ...targetKeys]"@check="(_, props) => {onLeftChecked(_, props, [...selectedKeys, ...targetKeys], itemSelect);}"><template slot='custom' slot-scope='item'><div v-if="item.flag === '1'"> {{ item.title+'('+item.level+')' }}</div><div v-if="item.flag === '2'"><span :style="{width:'20px',height:'10px',background:item.color,padding:'5px 10px',marginRight:'5px'}">{{ item.levelText}}</span>{{ item.title}}</div></template></a-tree></div><div v-if="direction === 'right'"><div class="left-ipt"><a-input placeholder="搜索可选择内容"><a-icon slot="prefix" type="search"></a-icon></a-input><a-button type="primary" class="search-btn">搜索</a-button></div><div><div v-for="item in rightData" :key="item.key"><a-checkbox @change="(e) => handleRightChange(e, [...selectedKeys], itemSelect, item.key)"><span :style="{width:'20px',height:'10px',background:item.color,padding:'5px 10px',marginRight:'5px'}">{{ item.levelText}}</span>{{ item.title}}</a-checkbox></div></div></div></template></a-transfer></a-modal>
</template>
<script>
import { getAction} from '@api/manage'
export default {props: {riskVisible: {type: Boolean,default: false}},data() {return {dataSource: [], // selectedKeys: [],confirmLoading: false,targetKeys: [],treeData: [],navList:[{title: '颜色分类',},{title: '常用分类'},{title: '疾病分类'}],currentNav: 0,showLine: true,rightData: [],rightSelectKeys: [],};},computed: {renderTreeData() {return this.handleTreeData(this.treeData, this.targetKeys);},},created() {this.initData ();},methods: {initData () {getAction("/biz/bizFiveColorConfig/getTreeData",null).then(res => {if (res.success) {this.treeData = res.result;let resultTranferData = [];res.result.forEach(item => {resultTranferData.push({title: item.title, key: item.key});if(item.children && item.children !== null) {item.children.forEach(it => {resultTranferData.push({title: it.title,key: it.key,});})}})this.dataSource = resultTranferData;} else {this.treeData = [];this.dataSource = [];}})},handleTreeData(data, targetKeys = []) {data.forEach(item => {item['disabled'] = true;if (item.children && item.children != null) {item.children.forEach(it => {if(targetKeys.includes(it.key)) {it.disabled = true;} else {it.disabled = false}})}});return data;},handleRightChange(event, checkedKeys, itemSelect, key) {itemSelect(key, !this.isChecked(checkedKeys, key));const { target } = event;if(target.checked) {this.rightSelectKeys.push(key);this.rightSelectKeys = [...new Set(this.rightSelectKeys)];}},isChecked(selectedKeys, eventKey) {return selectedKeys.indexOf(eventKey) !== -1;},onChange(targetKeys, direction) {if(direction == 'right') {this.targetKeys = targetKeys;let resultData = [];this.treeData.forEach(item => {if(item.children && item.children != null) {}item.children.forEach(it => {if(this.targetKeys.includes(it.key)) {resultData.push(it);}})})this.rightData = resultData;} else {const resKeys = [];const resRightData = [];this.rightData.forEach(item => {if(!this.rightSelectKeys.includes(item.key)) {resKeys.push(item.key);resRightData.push(item);}})this.targetKeys = resKeys;this.rightData = resRightData;}},// 左侧复选框选中onLeftChecked(_, e, checkedKeys, itemSelect) {const { eventKey } = e.node;itemSelect(eventKey, !this.isChecked(checkedKeys, eventKey));},// 确认handleOk() {const chooseFactorArr = [];this.treeData.forEach(item => {let children = [];if(item.children && item.children != null) {children = item.children.filter(it => it.disabled);if(children.length) {chooseFactorArr.push({...item,children})}}})this.confirmLoading = true;setTimeout(() => {this.$emit('handleRiskVisible', { bool: false, chooseFactorArr})this.confirmLoading = false;}, 1000);},// 取消handleCancel() {this.$emit('handleRiskVisible', { bool: false})},// nav切换handleNavChange(index) {this.currentNav = index;}},
};
</script>
<style scoped lang="less">.left-ipt {display: flex;margin: 15px 0 13px;
}.search-btn {margin-left: 8px;
}.nav-list {display: flex;cursor: pointer;
}.nav-item {padding: 0 8px;height: 24px;line-height: 24px;background: #EEEEEE;border-radius: 4px;margin-right: 16px;font-size: 12px;font-weight: 400;color: #333333;
}.current-color {background: #2AB967;color: white;
}.right-ipt {display: flex;
}/deep/.ant-modal-footer {border-top: none;padding: 4px 24px 30px;
}.tips {margin-top: 10px;font-size: 14px;color: #666666;line-height: 20px;
}/deep/.ant-transfer-list-content-item {padding: 0 12px;
}/deep/.ant-transfer-list {border: none;
}/deep/.ant-transfer-list-header {border-bottom: none;border-radius: 0;
}/deep/.ant-transfer-list-body {border-radius: 4px;border: 1px solid #DDDDDD;
}/deep/.ant-transfer-list-header-selected span:first-child {position: relative;left: 100px;font-size: 12px;color: #999999;
}
.folder-icon {width: 14px;height: 11px;margin: 4px 0 6px 0;
}
/deep/.ant-transfer-list-header-title {left: 0;font-size: 14px;font-weight: 500;color: #333333;
}/deep/.ant-input-affix-wrapper {color: #999999;
}/deep/.ant-transfer-list {width: 100%;overflow: auto;
}/deep/.ant-tree.ant-tree-block-node li span.ant-tree-checkbox + .ant-tree-node-content-wrapper {text-overflow: ellipsis;overflow: hidden;white-space: nowrap;
}
</style>
2、以上需要注意的点:
dataSource做为穿梭框的数据源需要是一维数组,并且里面的属性title和key都要为string类型,不然就会报错(dataSource类型不正确)
3、最终实现的效果