el-tree-select是一个含有下拉菜单的树形选择器,结合了 el-tree 和 el-select 两个组件的功能。
因为包含了el-tree的功能,我们可以自定义tree的节点,创造出想要的组件
使用default插槽可以自定义节点内容,它的default插槽相当于el-tree的default插槽
<template>
<el-tree-select
v-model="dirCode"
:data="treeData"
:highlight-current="true"
:props="defaultProps"
clearable
filterable
node-key="pathCode"
:placeholder="placeholder"
@clear="handleClear">
<template #default="{ node, data }">
<div class="custom-tree-node" @click="data.pathCode !== '-1' ? handleNodeClick(data) : ''">
<div class="tree-icon">
<svg-icon class="file" icon-class="file">svg-icon>
div>
<div class="tree-label one-line">
<span class="tree-label-text one-line">
{{ node.label }}
span>
div>
div>
template>
el-tree-select>
template>
使用:model-value="modelValue"可以在适合用组件时直接v-model绑定值
我这里使用的是setup式的语法,当然也可以使用setup()方法
<script setup>
import { ref, reactive, watch, onMounted } from 'vue'
import { getDirectory } from 'api/autoOperations/scriptManage'
const props = defineProps({
placeholder: {
type: String,
default: '请选择目录',
required: false
},
code: {
type: String,
default: '',
required: false
},
path: {
type: String,
default: '',
required: false
}
})
let dirCode = ref('')
let dirPath = ref('')
const treeData = ref([])
const emits = defineEmits(['change'])
// 树状图默认配置
const defaultProps = reactive({
children: 'children',
label: 'pathName',
isLeaf(data, node) {
return data.isLeaf == 'true'
}
})
watch(() => props.code, (val) => {
if (val) {
dirCode.value = val
}
}, {
immediate: true,
deep: true
})
watch(() => props.path, (val) => {
if (val) {
dirPath.value = val
}
}, {
immediate: true,
deep: true
})
onMounted(() => {
getTreeData()
})
// 这里从数据库获取数据
const getTreeData = () => {
}
const handleNodeClick = (data) => {
dirCode.value = data.pathCode
dirPath.value = data.dirPath
emits('change', {
dirPath: dirPath.value,
dirCode: dirCode.value
})
}
const handleClear = () => {
dirCode.value = ''
dirPath.value = ''
emits('change', {
dirPath: dirPath.value,
dirCode: dirCode.value
})
}
</script>
这是我的自定义样式,用的scss
<style lang="scss" scoped>
.custom-tree-node {
display: flex;
justify-content: space-between;
align-items: center;
width: calc(100% - 24px);
font-size: 12px;
line-height: 24px;
.tree-icon {
width: 20px;
display: flex;
align-items: center;
.file {
width: 20px;
font-size: 20px;
vertical-align: text-bottom;
}
}
.tree-label {
width: 100%;
height: 24px;
line-height: 24px;
.tree-label-text {
display: inline-block;
max-width: calc(100% - 30px);
}
}
}
style>
最后是效果图