0%

Element tree树组件 鼠标双击事件

需求

双击 tree上的子节点,把节点文字显示在输入框中(这里简化一下,双击 tree 显示文字即可,省略 $emit 那一步)

  • 注解:props 可以接收 defaultExpandAll(是否默认展开所有节点)

效果如下:

因为 Element 的 tree 组件不支持双击事件,这时可以曲线救国试一下

基本代码

树组件代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<template>
<el-tree
id="tree"
v-loading="treeDataLoading"
node-key="id"
:data="treeData"
:default-expand-all="defaultExpandAll"
:expand-on-click-node="false"
style="height: 100%;"
/>
</template>

<script>
export default {
name: 'TreeDbl',
props: {
defaultExpandAll: {
type: Boolean,
default: false
}
},
data() {
return {
treeData: [],
treeDataLoading: false,
resData: [
{
id: '1',
label: '动物',
parentId: ''
},
{
id: '2',
label: '狗',
parentId: '1'
},
{
id: '3',
label: '哈士奇',
parentId: '2'
},
{
id: '4',
label: '柯基',
parentId: '2'
},
{
id: '6',
label: '猫',
parentId: '1'
},
{
id: '7',
label: '植物',
parentId: ''
}
]
}
},
created() {
this.getTree()
},
methods: {
dblClickItem(e) {
if (e.target.nodeName === 'SPAN') {
console.log(e.target.innerText)
}
},
/*
以下处理数据逻辑可以直接跳过
*/
getTree() {
this.treeDataLoading = true
// 发送数据请求(这里不发送请求以resData模拟)
new Promise(resovle => {
const tree = this.resData
this.treeData = this.transfromData(tree)
resovle()
})
.catch(() => {})
.finally(() => {
this.treeDataLoading = false
})
},
transfromData(data, params = {}) {
// 深拷贝一份(以防连续调用出错)
const cData = JSON.parse(JSON.stringify(data))
const map = {}
const tData = []
const attr = {
id: 'id',
parentId: 'parentId'
}
const arg = Object.assign({}, attr, params)
// 注意:这里item的引用地址指向cData
cData.forEach(item => (map[item[arg.id]] = item))
cData.forEach(child => {
const mapItem = map[child[arg.parentId]]
if (mapItem) {
// 注意:这里mapItem引用地址指向也是指向cData
if (!mapItem.children) mapItem.children = []
mapItem.children.push(child)
} else {
// 顶级节点
tData.push(child)
}
})
return tData
}
}
}
</script>

父组件代码

1
<tree-dbl defaultExpandAll />

效果如下:

一个不太好的方案:直接添加事件绑定

可以直接给 tree添加事件绑定,利用事件委托显示每一个元素的文字信息,可以在 getTree 方法中的 finally 中添加如下代码

1
document.getElementById('tree').addEventListener('dblclick', this.dblClickItem)
  • 也可以借助 @node-expand(节点被展开时触发的事件) 和 @node-collapse (节点被关闭时触发的事件)添加/解除事件绑定,不过有些麻烦
  • 也可以使用 @node-click (节点被点击时的回调),记录点击次数,由于 @node-click 可以拿到点击节点的 data,可以对其进行是否是根节点的判断

推荐方案:使用自定义节点内容

可以在节点区添加按钮或图标等内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<el-tree
id="tree"
ref="tree"
v-loading="treeDataLoading"
node-key="id"
:data="treeData"
:default-expand-all="defaultExpandAll"
:expand-on-click-node="false"
style="height: 100%;"
>
<span class="custom-tree-node" slot-scope="{ node }">
<span @dblclick="dblClickItem">{{ node.label }}</span>
</span>
</el-tree>
</template>
>

<style scoped>
.custom-tree-node {
font-size: 14px;
}
</style>