一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
序
项目上需要有树形结构的下拉选择需要,展示树形结构数据
结合Vue3、TypeScript、Element Plus
封装该组件
项目搭建
基于之前文章的框架封装,使用Vite搭建Vue3项目实践记录 - 掘金 (juejin.cn)
已有Vite、Vue3、TypeScript、Element Plus
,并带有ESlint
代码规范
可根据需要全局引入或按需引入Element Plus
开始
子组件
项目搭建后,在components
文件夹下新建treeSelect.vue
文件
html
部分是el-input、el-popover、el-tree
组合而成的,input
不需要输入所以要设置readonly
input
的值一般是label
用作展示的文字,真正选择的值是propsValue
el-tree
的data、props
还有其他的值都可以从父组件传入
<template>
<div>
{{ propsValue }}
</div>
<el-popover placement="bottom-start" :width="200" trigger="click">
<template #reference>
<el-input v-model="state.label" style="width: 240px" readonly placeholder="Please input" />
</template>
<el-tree :data="props.treeData" :props="props.defaultProps" @node-click="handleNodeClick" />
</el-popover>
</template>
js
部分是用了script setup
的写法
<script lang="ts" setup>
import { computed, reactive } from "vue";
const props = defineProps({
modelValue: {
type: String,
default: ""
},
treeData: {
type: Array,
default: () => []
},
defaultProps: {
type: Object,
default: () => {
return {
children: "children",
label: "label"
};
}
}
});
const propsValue = computed(() => props.modelValue);
const state = reactive({
label: ""
});
const emit = defineEmits(["update:modelValue"]);
const handleNodeClick = (data: any) => {
state.label = data.label;
emit("update:modelValue", data.id);
};
</script>
需要注意几点
第一是props
中的数组和对象的默认值default
都需要用函数返回
第二,modelValue
是父组件v-model
传入的值,如果在子组件的input
中也使用
v-model="props.modelValue"
会报错,所以可以选择使用computed
返回一个新的值
第三,修改modelValue
可以直接可以defineEmits(["update:modelValue"])
父组件
父组件就相对简单,负责传值就可以了
<template>
<div>
<tree-select v-model="state.select" :tree-data="state.treeData" :default-props="state.defaultProps"></tree-select>
</div>
</template>
<script setup lang="ts">
import { reactive } from "vue";
interface Tree {
id: number;
label: string;
children?: Tree[];
}
const state = reactive({
select: "123",
treeData: [
{
id: 1,
label: "Level one 1",
children: [
{
id: 11,
label: "Level two 1-1",
children: [
{
label: "Level three 1-1-1"
}
]
}
]
},
{
id: 2,
label: "Level one 2",
children: [
{
id: 21,
label: "Level two 2-1"
},
{
id: 22,
label: "Level two 2-2",
children: [
{
id: 23,
label: "Level three 2-2-1"
}
]
}
]
}
] as Tree[],
defaultProps: {
id: "id",
children: "children",
label: "label"
}
});
</script>
效果
选择后input展示节点的文字,并改变propValue的值
Element Plus的树形选择
在Element Plus
的2.18版本已经支持了树形选择,可单选或多选,建议升级Element Plus
使用
TreeSelect 树形选择 | Element Plus (gitee.io)
结束
后续可增加节点禁用,默认打开某些节点
欢迎点赞收藏