首先是页面部分
1
2
3
4
5
6
7
8
9
10
11
12
|
< template >
< el-tree
id = "userMtree"
ref = "tree"
:data = "treeData"
node-key = "id"
:render-content = "renderContent"
:expand-on-click-node = "false"
@ node-click = "nodeClick"
:default-expanded-keys = 'expandedKey'
></ el-tree >
</ template >
|
下面是js部分
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
|
export default {
props:[ 'treeDataObj' , 'isUserMgt' ], //父级传值 与判断哪个tree
data () {
return {
treeData:[], //tree数据
expandedKey:[], //展开节点
checkedID: '' //选中节点
}
},
mounted(){
this .treeData= this .treeDataObj.treeData
let userMtree=document.getElementById( 'userMtree' )
this .$nextTick(()=>{
userMtree.firstElementChild.classList.add( "is-current" ); //添加选中类名
})
this .checkedID= this .treeData[0].id //默认选中第一个
},
methods:{
//编辑
nodeEdit(ev, store, data) {
data.isEdit = true ;
this .$nextTick(() => { //得到input
const $input =
ev.target.parentNode.parentNode.querySelector( "input" ) ||
ev.target.parentElement.parentElement.querySelector( "input" );
!$input ? "" : $input.focus(); //获取焦点
});
},
//失焦事件
edit_sure(ev, data) {
const $input =
ev.target.parentNode.parentNode.querySelector( "input" ) ||
ev.target.parentElement.parentElement.querySelector( "input" );
if (!$input) {
return false ;
} else if ($input.value== '' ){
this .$message({
type: "info" ,
message: "内容不能为空!"
});
} else { //赋值value
data.label = $input.value;
data.isEdit = false ;
}
},
//react方法 插入代码
renderContent(h, { node, data, store }) {
return (
<span class= "custom-tree-node" >
<span class= "tree_node_label" >{ this .showOrEdit(data)}</span>
<div class= "tree_node_op" >
<i class= "el-icon-edit" on-click={ev => this .nodeEdit(ev, store, data)}/>
<i class= "el-icon-remove-outline"
on-click={() => this .nodeDelete(node, data)}/>
{
this .isUserMgt?<i class= "el-icon-circle-plus-outline"
on-click={() => this .append( data)}></i>: '' }
</div>
</span>
);
},
showOrEdit(data) {
if (data.isEdit) {
return (
<input type= "text" class= "node_labe" value={data.label}
on-blur={ev => this .edit_sure(ev, data)} />
);
} else {
return <span class= "node_labe" >{data.label}</span>;
}
},
//新增节点
append(data) {
const newChild = { id: new Date().getTime(), label: '' , children: [],
isEdit: true };
//判断是否有子节点
if (!data.children) {
this .$set(data, 'children' , []);
}
data.children.push(newChild);
this .expandedKey=[data] //展开点击节点
},
//移除节点
nodeDelete(node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const index = children.findIndex(d => d.id === data.id)
children.splice(index, 1)
},
//点击节点 移除默认选中节点
nodeClick(data){
let userMtree=document.getElementById( 'userMtree' )
userMtree.firstElementChild.classList.remove( "is-current" );
this .checkedID=data.id
console.log(data)
this .$emit( 'emitClickNode' ,data)
}
}
}
|
补充知识:vue前端基础之组件封装(树组件的封装附带增删改查方法)
组件封装的意义
组件封装的意义其实很好理解,对于一段复用性极高的代码,就需要进行组件封装以减少冗余代码。
树的封装
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
<template>
<el-aside width= "180px" >
<h3 class= "el-icon-folder" style= "margin: 0px" >
{{ name }}
</h3>
<el-tree
ref= "tree"
:data= "setTree"
:props= "defaultProps"
node-key= "id"
style= "margin-top:20px"
accordion
@node-contextmenu= "rihgtClick"
>
<span slot-scope= "{ node, data }" class= "span-ellipsis" >
<span v-show= "!node.isEdit" >
<span v-show= "data.children && data.children.length >= 1" >
<span :title= "node.label" >{{ node.label }}</span>
</span>
<span v-show= "!data.children || data.children.length == 0" >
<span :title= "node.label" > {{ node.label }}</span>
</span>
</span>
</span>
</el-tree>
<!--鼠标右键点击出现页面-->
<div v-show= "menuVisible" >
<el-menu
id= "rightClickMenu"
class= "el-menu-vertical"
text-color= "#000000"
active-text-color= "#000000"
@select= "handleRightSelect"
>
<el-menu-item index= "1" :hidden= "showQuery" class= "menuItem" >
<span slot= "title" >查询</span>
</el-menu-item>
<el-menu-item index= "2" :hidden= "showSave" class= "menuItem" >
<span slot= "title" >添加</span>
</el-menu-item>
<el-menu-item index= "3" :hidden= "showUpdate" class= "menuItem" >
<span slot= "title" >修改</span>
</el-menu-item>
<el-menu-item index= "4" :hidden= "showDelete" class= "menuItem" >
<span slot= "title" >删除</span>
</el-menu-item>
</el-menu>
</div>
</el-aside>
</template>
<script>
export default {
name: 'Tree' ,
props: {
treeData: {
type: Array,
required: true
},
treeName: {
type: String,
required: true ,
default : '树'
},
isHiddenQuery: {
type: Boolean,
required: false ,
default : true
},
isHiddenSave: {
type: Boolean,
required: false ,
default : false
},
isHiddenUpdate: {
type: Boolean,
required: false ,
default : false
},
isHiddenDelete: {
type: Boolean,
required: false ,
default : false
}
},
data() {
return {
setTree: this .treeData,
showQuery: this .isHiddenQuery,
showSave: this .isHiddenSave,
showUpdate: this .isHiddenUpdate,
showDelete: this .isHiddenDelete,
name: this .treeName,
TREEDATA: {
DATA: null ,
NODE: null
},
isLoadingTree: true , // 是否加载节点树
objectID: null ,
defaultProps: {
children: 'children' ,
label: 'name'
},
menuVisible: this .menuVisible
}
},
watch: {
treeData(val) {
this .setTree = val
},
treeName(val) {
this .name = val
}
},
methods: {
handleRightSelect(key) {
if (key === '1' ) {
this .$emit( 'NodeQuery' , this .TREEDATA)
this .menuVisible = false
} else if (key === '2' ) {
this .$emit( 'NodeAdd' , this .TREEDATA)
this .menuVisible = false
} else if (key === '3' ) {
this .$emit( 'NodeUpdate' , this .TREEDATA)
this .menuVisible = false
} else if (key === '4' ) {
this .$emit( 'NodeDel' , this .TREEDATA)
this .menuVisible = false
}
},
rihgtClick(event, object, value, element) {
if ( this .objectID !== object.id) {
this .objectID = object.id
this .menuVisible = true
this .TREEDATA.DATA = object
this .TREEDATA.NODE = value
} else {
this .menuVisible = ! this .menuVisible
}
document.addEventListener( 'click' , e => {
this .menuVisible = false
})
const menu = document.querySelector( '#rightClickMenu' )
/* 菜单定位基于鼠标点击位置 */
menu.style.left = event.clientX - 180 + 'px'
menu.style.top = event.clientY - 100 + 'px'
menu.style.position = 'absolute' // 为新创建的DIV指定绝对定位
menu.style.width = 120 + 'px'
}
}
}
</script>
<style lang= "scss" scoped>
.span-ellipsis {
width: 100%;
overflow: hidden;
margin-left: 10px;
white-space: nowrap;
text-overflow: ellipsis;
}
</style>
|
对于组件的引用
1
2
3
4
5
|
import tree from '@/components/Tree/index'
export default {
components: { tree },
data() {}
......
|
组件的使用
1
2
3
4
5
6
7
|
<tree
:tree-data= "setTree"
:tree-name= "treeName"
@NodeAdd= "NodeAdd"
@NodeUpdate= "NodeUpdate"
@NodeDel= "NodeDel"
/>
|
setTree是要给树赋予的值,treeName是树的标题(可不要),后面是需要的树的右键操作我启用了增删改
效果图
子组件向父组件传值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
handleRightSelect(key) {
if (key === '1' ) {
this .$emit( 'NodeQuery' , this .TREEDATA)
this .menuVisible = false
} else if (key === '2' ) {
this .$emit( 'NodeAdd' , this .TREEDATA)
this .menuVisible = false
} else if (key === '3' ) {
this .$emit( 'NodeUpdate' , this .TREEDATA)
this .menuVisible = false
} else if (key === '4' ) {
this .$emit( 'NodeDel' , this .TREEDATA)
this .menuVisible = false
}
}
|
以上这篇element-ui tree结构实现增删改自定义功能代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/qq_37818095/article/details/86299336