vue3.0+TS+antdesgin 选择树(tree)的增删改查(简单封装)
效果图:
父组件代码:
<div class="tree-box">
<type-tree @onSelect="onSelect" :action="true"/>
</div>
子组件代码:
<template>
<div class="tree">
<a-tree
show-line
:treeData="treeData"
:defaultExpandAll="true"
@select.self="onSelect"
v-if="treeData.length"
:replaceFields="replaceFields"
v-model:selectedKeys="selectedKeys"
>
<!-- @click.prevent="((e)=>{e.stopPropagation()})" :阻止默认事件向后传播 -->
<template v-slot:title="nodeData">
<a-input
style="width: 100px"
:ref="childId === nodeData.len ? 'inputVal' : 'inputTest'"
@click.prevent="
(e) => {
e.stopPropagation();
}
"
@blur="addSumbit(nodeData)"
v-if="nodeData.isEdit"
v-model:value="inputTypeName"
/>
<span v-if="!nodeData.isEdit">{{ nodeData.typeName }}</span>
<a-button-group class="editBox" v-if="action">
<a-button type="link" size="small" @click.stop="slotAdd(nodeData)" title="添加">
<template #icon><PlusOutlined /></template>
</a-button>
<a-button type="link" size="small" @click.stop="slotEdit(nodeData)" title="修改">
<template #icon><EditOutlined /></template>
</a-button>
<a-button type="link" size="small" @click.stop="slotDelete(nodeData)" title="删除">
<template #icon><DeleteTwoTone twoToneColor="#eb2f96" /></template>
</a-button>
</a-button-group>
</template>
</a-tree>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref, reactive, nextTick, createVNode } from 'vue';
import { SelectEvent } from 'ant-design-vue/es/tree/Tree';
import { adminApi, treeEdit } from '/@/api/index';
import { message, Modal } from 'ant-design-vue';
import {
PlusOutlined,
EditOutlined,
DeleteTwoTone,
ExclamationCircleOutlined,
} from '@ant-design/icons-vue';
export default defineComponent({
props: {
action: {
type: Boolean,
required: false,
},
},
components: {
PlusOutlined,
EditOutlined,
DeleteTwoTone,
},
setup(props, { emit }) {
// 替换 treeNode 中 title,key,children 字段为 treeData 中对应的字段
let replaceFields: object = reactive({
title: 'typeName',
key: 'id',
});
// 用于点击添加时总是让第一个输入框获取焦点
let childId = ref(0);
// tree的数据
let treeData = ref([]);
// 定义ref值
let inputVal = ref<any>(null);
let inputTest = ref<any>('inoputTest');
// 输入框内容
let inputTypeName = ref<string>('新建类型');
// 刷新组件
let flag = ref<boolean>(true);
// 用于判断是点击添加还是编辑
let editOperation = ref<string>('');
onMounted(() => {
getTreeData();
});
function onSelect(selectedKeys: string[], event: SelectEvent) {
emit('onSelect', selectedKeys);
}
// 获取树列表
async function getTreeData() {
let tree: Array<object> = [];
let tree1: Array<object> = [];
let tree2: Array<object> = [];
let res = await adminApi.TreeDataApi();
res.obj.forEach((item: any) => {
if (item.parentId === '0') {
item.children = [];
tree.push(item);
}
for (let node of tree) {
getChildren(node, res.obj);
}
});
tree.forEach((item: any) => {
// 给数组里的每一个对象都添加一个isEdit属性
item.isEdit = false;
for (let i of item.children) {
i.isEdit = false;
tree1.push(i);
}
tree2.push(item);
onSelect(item.id);
});
treeData.value = tree2;
}
function getChildren(node: any, dataList: any) {
for (let item of dataList) {
if (!item.children) {
item.children = [];
}
if (item.parentId === node.id) {
node.children.push(item);
}
}
if (node.children === []) {
return;
}
for (let child of node.children) {
getChildren(child, dataList);
}
}
// 点击添加按钮
function slotAdd(nodeItem: any) {
editOperation.value = 'add';
let len = nodeItem.children.length || 0;
childId.value = len;
// 上面这里你看下
nodeItem.children.unshift({
len,
id: null,
isEdit: true,
key: new Date().getTime(),
parentId: nodeItem.id,
children: [],
});
// 点击添加让新增的输入框获取焦点
nextTick(() => {
inputVal.value.focus();
});
}
// 新增、编辑时input框失去焦点触发事件
async function addSumbit(nodeItem: any) {
let params = {
id: nodeItem.id || null,
parentId: nodeItem.parentId,
typeName: inputTypeName.value,
};
let res =
editOperation.value === 'add'
? await treeEdit.insertType(params)
: await treeEdit.updateType(params);
if (res.success) {
nodeItem.isEdit = false;
getTreeData();
message.success(res.msg);
} else {
message.error(res.msg);
}
}
// 点击编辑
async function slotEdit(nodeItem: any) {
editOperation.value = 'edit';
treeData.value.forEach((item: any) => {
if (item.id === nodeItem.id) {
item.isEdit = true;
inputTypeName.value = nodeItem.typeName;
}
for (let i of item.children) {
if (i.id === nodeItem.id) {
i.isEdit = true;
inputTypeName.value = nodeItem.typeName;
}
}
// 点击编辑时让输入框获取焦点
nextTick(() => {
inputTest.value.focus();
});
});
console.log('nodeItem', nodeItem); //这是传点那个树的分支 传过来的树的属性
}
// 点击删除
function slotDelete(nodeItem: any) {
let params = {
id: nodeItem.id,
};
Modal.confirm({
title: '删除',
icon: createVNode(ExclamationCircleOutlined),
content: '你确定要删除吗?',
okText: 'Yes',
okType: 'danger',
cancelText: 'No',
async onOk() {
const res = await treeEdit.deleteType(params);
if (res.success) {
getTreeData();
message.success(res.msg);
} else {
message.error(res.msg);
}
},
});
}
return {
onSelect,
treeData,
replaceFields,
slotAdd,
slotEdit,
slotDelete,
childId,
inputVal,
inputTest,
inputTypeName,
addSumbit,
flag,
editOperation,
};
},
});
</script>
<style lang="scss" scoped>
.editBox {
margin-left: 7px;
}
</style>