antd的穿梭框的数据貌似只接收key和title,而且必须是字符串(我测试不是字符串的不行),
所以要把后端返回的数据再处理一下得到我们想要的数据
除了实现简单的穿梭框功能,还想要重写搜索事件,想达到的效果是搜索到的结果的节点能自动展开且高亮显示
给穿梭框添加show-search
完整代码:
<template>
<!-- 选择图层穿梭框 -->
<a-modal title="选择数据图层" width="900px" :visible="true" :maskClosable="false" wrapClassName="transferModal"
centered @ok="getSelectedNodes" destroyOnClose>
<a-transfer
class="tree-transfer"
:titles="['所有数据图层', '已选数据图层']"
:operations="['添加', '移除']"
:data-source="dataSource"
:target-keys="targetKeys"
:render="item => item.title"
:show-select-all="false"
@change="onChange"
show-search
@search="handleSearch"
>
<template
slot="children"
slot-scope="{ props: { direction, selectedKeys }, on: { itemSelect } }"
>
<a-tree
v-if="direction === 'left'"
blockNode
checkable
checkStrictly
defaultExpandAll
:checkedKeys="[...selectedKeys, ...targetKeys]"
:treeData="newTreeData"
:expandedKeys="expandedKeys" :auto-expand-parent="autoExpandParent"
@expand="onExpand"
@check="
(_, props) => {
onChecked(_, props, [...selectedKeys, ...targetKeys], itemSelect);
}
"
@select="
(_, props) => {
onChecked(_, props, [...selectedKeys, ...targetKeys], itemSelect);
}
"
>
<template slot="title" slot-scope="{ name }">
<span v-if="name.indexOf(searchValue) > -1">
{{ name.substr(0, name.indexOf(searchValue)) }}
<span style="color: #f50">{{ searchValue }}</span>
{{ name.substr(name.indexOf(searchValue) + searchValue.length) }}
</span>
<span v-else>{{ name }}</span>
</template>
</a-tree>
</template>
</a-transfer>
</a-modal>
</template>
<script>
import { auth_service_tree_zyfx } from "@/API/api/g_api"
function isChecked(selectedKeys, eventKey) {
return selectedKeys.indexOf(eventKey) !== -1;
}
function handleTreeData(data, targetKeys = []) {//数据选中移到右侧就设置为禁选
data.forEach(item => {
item['disabled'] = targetKeys.includes(item.key);
if (item.children) {
handleTreeData(item.children, targetKeys);
}
});
return data;
}
const getParentKey = (key, tree) => {
let parentKey;
for (let i = 0; i < tree.length; i++) {
const node = tree[i];
if (node.children) {
if (node.children.some((item) => item.id === key)) {
parentKey = String(node.id);
} else if (getParentKey(key, node.children)) {
parentKey = getParentKey(key, node.children);
}
}
}
return parentKey;
};
const dataList = [];
const generateList = (data) => {
for (let i = 0; i < data.length; i++) {
const node = data[i];
const key = node.id;
const name = node.name;
dataList.push({ key, title: name });
if (node.children) {
generateList(node.children);
}
}
};
export default {
data() {
return {
treeData: [],
targetKeys: [],
dataSource: [],
checkedNodes: [],
dataList: [],
expandedKeys: [],
searchValue: "",
autoExpandParent: true,
}
},
computed: {
newTreeData() {
return handleTreeData(this.treeData, this.targetKeys);
},
},
mounted(){
this.init();
},
methods:{
async init(){
let data = await auth_service_tree_zyfx()
this.treeData = data.code==1?data.data:[];
this.renderTreeNodes(this.treeData)
//console.log(this.treeData);
//generateList(this.treeData);
this.flatten(JSON.parse(JSON.stringify(this.treeData)));
},
renderTreeNodes(list) {
list.forEach(item => {
item.key = String(item.id);
item.title = item.name;
this.dataList.push({ key: item.id, title: item.name });
if(item.children){
this.renderTreeNodes(item.children);
}
});
},
flatten(list = []) {
list.forEach(item => {
this.dataSource.push(item);
this.flatten(item.children);
});
},
onChange(targetKeys) { //两栏之间转移时的回调函数
// console.log('Target Keys:', targetKeys);
this.targetKeys = targetKeys;
},
onChecked(_, e, checkedKeys, itemSelect) {//选中项发生改变时的回调函数
// console.log(_, e.checkedNodes, checkedKeys, itemSelect);
this.checkedNodes = e.checkedNodes;
const { eventKey } = e.node;
itemSelect(eventKey, !isChecked(checkedKeys, eventKey));
},
onExpand(expandedKeys) {
this.expandedKeys = expandedKeys;
this.autoExpandParent = false;
},
handleSearch(dir, value) {
// console.log('search:', dir, value);
if(dir=="left"){
const expandedKeys = this.dataList
.map((item) => {
if (item.title.toString().indexOf(value) > -1) {
return getParentKey(item.key, this.treeData);
}
return null;
})
.filter((item, i, self) => item && self.indexOf(item) === i);
// console.log(expandedKeys);
Object.assign(this, {
expandedKeys,
searchValue: value,
autoExpandParent: true,
});
}
},
getSelectedNodes(){
let nodes = [];
this.checkedNodes.map(r=>{
if(this.targetKeys.includes(r.key)){
nodes.push(r.data.props.dataRef)
}
});
console.log(nodes);
}
}
};
</script>
<style lang="scss" scoped>
::v-deep .transferModal{
.ant-modal-body{
max-height: 70vh;
// overflow-y: auto;
.tree-transfer{
height: 100%;
}
.ant-transfer-list-body{
max-height: 300px;
overflow: auto;
}
}
}
</style>
实现效果如下: