elementPlus 树滑动显示增删且改写节点为下拉框
需求:鼠标滑过树节点 显示增删改按钮,且可改选值,节点为下拉框
效果图:
改写为下拉框的思路:
因为el-option展开只能依靠el-select 所以不可以把el-option单独提出来 只能当点击下拉框小按钮的时候把原来树节点的span标签替换为下拉框标签 然后让下拉框自动展开 后改写下拉框的样式
附上完整代码:
<template>
<el-tree
:allow-drop="allowDrop"
:allow-drag="allowDrag"
:data="dataSource"
draggable
default-expand-all
node-key="id"
ref="one"
highlight-current
:expand-on-click-node="false"
>
<template #default="{ node, data }">
<span class="custom-tree-node" @mouseleave="mouseLeave(data)">
<span class="treeLabel" @mouseenter="mouseEnter(data)" v-if="!data.isSelect">{{ data.label }}</span>
<el-select
v-if="data.isSelect"
v-model="data.optionValue"
:teleported="true"
size="small"
ref="selectRef"
class="selectClass"
@change="selectChange($event,data)"
@visible-change="selectVisibleChange($event,data)"
suffix-icon="none"
popper-class="optionClass"
:fit-input-width="false"
>
<el-option id="selectOption"
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
<span>{{item.label}}</span>
</el-option>
</el-select>
<span @click="chooseIcon(data,node)"><el-icon><ArrowDown /></el-icon></span>
<span class="textLink" v-if="data.isHover">
<a @click.stop="append(data)"><el-icon color="#3E5ECD"><CirclePlus /></el-icon></a>
<a style="margin-left: 8px" @click.stop="remove(node, data)"> <el-icon color="#3E5ECD"><Delete /></el-icon> </a>
</span>
</span>
</template>
</el-tree>
</template>
<script lang='ts'>
import { defineComponent, reactive, ref, nextTick, onMounted } from 'vue'
import type Node from 'element-plus/es/components/tree/src/model/node'
import type { NodeDropType } from 'element-plus/es/components/tree/src/tree.type'
import { ElSelect, ElTree } from 'element-plus'
import treeData from '@/utils/treeData'
export default defineComponent({
name: 'oneFour',
setup() {
interface Tree {
id: number
label: string
children?: Tree[]
}
let one = ref<InstanceType<typeof ElTree>>()
let selectRef = ref<InstanceType<typeof ElSelect>>()
const allowDrop = (draggingNode: Node, dropNode: Node, type: NodeDropType) => {
return false
}
const allowDrag = (draggingNode: Node) => {
return true
}
const append = (data: Tree) => {
const newChild = { id: num++, label: 'node', children: [] }
if (!data.children) {
data.children = []
}
data.children.push(newChild)
dataSource.value = [...dataSource.value]
}
const remove = (node: Node, data: Tree) => {
const parent = node.parent
const children: Tree[] = parent.data.children || parent.data
const index = children.findIndex((d) => d.id === data.id)
children.splice(index, 1)
dataSource.value = [...dataSource.value]
}
const dataSource = ref(treeData)
let num:number = 100
const mapData = (data:any)=>{
for(let i in data){
let element = data[i]
element.id = num++
element.isHover = false;
element.isSelect = false;
element.optionValue = element.label;
mapData(element.children)
}
}
const mouseLeave = (data:any)=>{
data.isHover = false
}
const mouseEnter = (data:any)=>{
data.isHover = true
}
const options = ref([
{
label:'大米饭',
value:'001'
},
{
label:'小米饭',
value:'002'
},
{
label:'玉米饭',
value:'003'
},
{
label:'糙米饭',
value:'004'
}
])
const chooseIcon = (data:any,node:any)=>{
data.isSelect = true;
nextTick(()=>{
selectRef.value!.toggleMenu()
})
}
const selectChange = (val:any,data:any)=>{
let s = options.value.filter((d:any)=>d.value == val)
data.label = s[0].label;
data.selectOption = val;
data.isSelect = false
}
const selectVisibleChange = (val:any,data:any)=>{
if(val == false){
data.isSelect = false
}
}
onMounted(()=>{
mapData(dataSource.value)
})
return {
allowDrop,
allowDrag,
dataSource,
append,
remove,
mouseEnter,
mouseLeave,
chooseIcon,
selectChange,
selectVisibleChange,
options,
selectRef
}
}
})
</script>
<style scoped>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
font-size: 14px;
padding-right: 8px;
}
.textLink{
margin-left: 10%;
color: #3E5ECD;
}
.treeLabel{
margin-right: 20px;
}
.selectClass{
width: 50%;
--el-select-input-focus-border-color:transparent !important;
--el-input-bg-color:transparent !important;
}
.selectClass :deep(.el-select .el-input.isfocus .el-input__wrapper){
box-shadow: none !important;
background-color: transparent !important;
}
.selectClass :deep(.el-select){
--el-select-input-focus-border-color:transparent !important;
--el-input-bg-color:transparent !important;
}
.selectClass :deep(.el-input__wrapper){
background-color: transparent !important;
}
.selectClass :deep(.el-input__inner){
color: #606266 !important;
font-weight: 600;
font-size: 14px !important;
}
.selectClass :deep(.el-input__suffix-inner){
display: none !important;
}
.selectClass :deep(.el-select-dropdown__item){
padding:0 10px !important;
}
.selectClass :deep(.el-select-dropdown optionClass){
min-width: 100px !important;
}
</style>
俺的项目链接 可参考:https://gitee.com/sydsdz/vue3_element-plus_ts