功能描述:
4、双击节点或点击修改节点 都可以对节点获取焦点并进行修改,回车修改成功
6、右击节点可进行增删改
效果图:
html布局:
html代码
<div class="tree-container">
<el-input placeholder="输入关键字进行过滤" v-model="filterText" class="search">
</el-input>
<el-tree :data="treeData" node-key="id" default-expand-all @node-click="handleLeftclick"
@node-drag-start="handleDragStart" @node-drag-enter="handleDragEnter" @node-drag-leave="handleDragLeave"
@node-drag-over="handleDragOver" @node-drag-end="handleDragEnd" @node-drop="handleDrop"
@node-contextmenu="rightClick" :filter-node-method="filterNode" draggable :allow-drop="allowDrop"
:allow-drag="allowDrag" ref="tree" class="tree-line">
<span class="slot-t-node" slot-scope="{ node, data }" @dblclick="editNode(data)">
<span v-show="!data.isEdit">
<span :class="[data.id >= 99 ? 'slot-t-node--label' : '']">
<i v-if="data.type == 'catalog'" class="el-icon-folder" />
<i v-if="data.type == 'menu'" class="el-icon-tickets" />
<i v-if="data.type == 'submenu'" class="el-icon-document" />
<span> {{ node.label }}</span>
</span>
</span>
<span v-show="data.isEdit">
<el-input class="slot-t-input" size="mini" autofocus v-model="data.label" :ref="'slotTreeInput' + data.id"
@blur.stop="NodeBlur(node, data)" @keydown.native.enter="NodeBlur(node, data)"></el-input>
</span>
</span>
</el-tree>
<div class="box-menu" v-show="menuVisible" :style="{ left: menu_left + 'px', top: menu_top + 'px' }">
<div @click="addSameLevelNode(0)" v-show="firstLevel">
<i class="el-icon-circle-plus-outline"></i>&nbsp;&nbsp;同级增加
</div>
<div class="add" @click="addChildNode()">
<i class="el-icon-circle-plus-outline"></i>&nbsp;&nbsp;子级增加
</div>
<div class="delete" @click="deleteNode()">
<i class="el-icon-remove-outline"></i>&nbsp;&nbsp;删除节点
</div>
<div class="edit" @click="editNode()">
<i class="el-icon-edit"></i>&nbsp;&nbsp;修改节点
</div>
</div>
</div>
CSS样式
<style scoped lang="less">
.el-tree>.is-leaf {
color: transparent;
}
.tree-container /deep/ .el-tree-node__expand-icon.expanded {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
.tree-container /deep/ .el-tree-node__expand-icon.expanded {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
.tree-container /deep/ .el-icon-caret-right:before {
background: url("../../assets/node-collapse.png") no-repeat;
content: '';
display: block;
width: 12px;
height: 12px;
font-size: 12px;
background-size: 10px;
}
/*
//有子节点 且已展开*/
.tree-container /deep/ .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
background: url("../../assets/node-expand.png") no-repeat;
content: '';
display: block;
width: 12px;
height: 12px;
font-size: 12px;
background-size: 10px;
}
/* //没有子节点*/
.tree-container /deep/ .el-tree-node__expand-icon.is-leaf::before {
background: transparent no-repeat 0 3px;
content: '';
display: block;
width: 12px;
height: 12px;
font-size: 12px;
background-size: 10px;
}
/* 点击节点时的选中颜色 */
.tree-container /deep/.el-tree-node.is-current>.el-tree-node__content {
color: #3D5ECC !important;
}
.tree-container /deep/ .el-tree-node__expand-icon {
margin-left: 15px;
// padding: 0px;
}
.tree-container /deep/ .el-tree-node__expand-icon.is-leaf {
margin-left: 0px;
}
.tree-container /deep/ .el-tree-node {
position: relative;
padding-left: 16px;
}
.tree-container /deep/ .el-tree-node__children {
padding-left: 16px;
}
.tree-container /deep/ .el-tree>.el-tree-node:before {
border-left: none;
}
.tree-container /deep/ .el-tree>.el-tree-node:after {
border-top: none;
}
.tree-container /deep/ .el-tree>.el-tree-node:before {
border-left: none;
}
.tree-container /deep/ .el-tree>.el-tree-node:after {
border-top: none;
}
.tree-container /deep/ .el-tree-node:before {
content: "";
left: 10px;
position: absolute;
right: auto;
border-width: 1px;
}
.tree-container /deep/ .el-tree-node:after {
content: "";
left: 10px;
position: absolute;
right: auto;
border-width: 1px;
}
.tree-container /deep/ .el-tree-node:before {
border-left: 1px dashed #ccc;
bottom: 0px;
height: 100%;
top: -19px;
width: 1px;
}
.tree-container /deep/ .el-tree-node:after {
border-top: 1px dashed #ccc;
height: 25px;
top: 20px;
width: 20px;
}
.el-tree-node :last-child:before {
height: 40px;
}
.tree-container {
margin: 10px;
}
.tree-container /deep/ .el-tree .el-tree-node {
position: relative;
}
.tree-container /deep/ .el-tree-node .el-tree-node__content {
height: 34px;
padding-left: 0px !important;
border: none;
}
.tree-container /deep/ .el-tree-node .el-tree-node__content::before {
border-left: 1px dashed #ccc;
height: 100%;
top: 0;
width: 1px;
margin-left: 1px;
margin-top: 0px;
z-index: 8;
}
.tree-container /deep/ .el-tree-node .el-tree-node__children .el-tree-node__content::before {
border-left: 0px dashed #ccc;
height: 100%;
top: 0;
width: 1px;
margin-left: 1px;
margin-top: 0px;
z-index: 8;
}
.tree-container /deep/ .el-tree-node .el-tree-node__content::after {
border-top: 1px dashed #ccc;
height: 1px;
top: 18px;
width: 13px;
margin-left: 1px;
z-index: 8;
}
.tree-container /deep/ .el-tree-node .el-tree-node__children .el-tree-node__content::after {
border-top: 0px dashed #ccc;
}
.tree-container .el-tree-node .el-tree-node__content::before,
.tree-container .el-tree-node .el-tree-node__content::after {
content: "";
position: absolute;
right: auto;
}
.el-tree {
width: 20%;
margin-top: 10px;
}
.search {
width: 20%;
cursor: pointer;
}
.box-menu {
width: 150px;
position: absolute;
z-index: 1000;
background-color: #fff;
box-shadow: 0px 0px 10px #ccc, 0px 0px 20px #ccc, 0px 0px 30px #ccc;
padding: 10px;
div {
cursor: pointer;
line-height: 30px;
}
div:active {
color: blue;
}
}
</style>
输入框校验
NodeBlur(Node, data) {
console.log(Node, data)
if (data.label.length === 0) {
this.$message.error('菜单名不可为空!')
return false
} else {
if (data.isEdit) {
this.$set(data, 'isEdit', false)
console.log(data.isEdit)
}
this.$nextTick(() => {
this.$refs['slotTreeInput' + data.id].$refs.input.focus()
})
}
},
查询功能
// 查询
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
watch: {
filterText(val) {
this.$refs.tree.filter(val)
}
},
拖拽功能
allowDrop(draggingNode, dropNode, type) {
if (dropNode.data.label === '二级 3-1') {
return type !== 'inner'
} else {
return true
}
},
allowDrag(draggingNode) {
return draggingNode.data.label.indexOf('三级 3-2-2') === -1
},
handleDragStart(node, ev) {
console.log('drag start', node)
},
handleDragEnter(draggingNode, dropNode, ev) {
console.log('tree drag enter: ', dropNode.label)
},
handleDragLeave(draggingNode, dropNode, ev) {
console.log('tree drag leave: ', dropNode.label)
},
handleDragOver(draggingNode, dropNode, ev) {
console.log('tree drag over: ', dropNode.label)
},
handleDragEnd(draggingNode, dropNode, dropType, ev) {
console.log('tree drag end: ', dropNode && dropNode.label, dropType)
},
handleDrop(draggingNode, dropNode, dropType, ev) {
console.log('tree drop: ', dropNode.label, dropType)
},
鼠标事件
// 鼠标右击事件
rightClick(event, object, Node, element) {
console.log(event, object)
this.currentData = object
this.currentNode = Node
if (Node.level === 1) {
this.firstLevel = true
} else {
this.firstLevel = false
}
this.menuVisible = true
document.addEventListener('click', this.foo)
// 将菜单显示在鼠标点击旁边定位
this.menu_left = event.clientX -140;
this.menu_top = event.clientY - 40;
},
// 鼠标左击事件
handleLeftclick(data, node) {
this.foo()
},
// 取消鼠标监听事件 菜单栏
foo() {
this.menuVisible = false
// 要及时关掉监听,不关掉的是一个坑,不信你试试,虽然前台显示的时候没有啥毛病,加一个alert你就知道了
document.removeEventListener('click', this.foo)
},
增加同级节点事件
// 增加同级节点事件
addSameLevelNode() {
let id = Math.ceil(Math.random() * 100)
var data = { id: id, label: '新增节点' }
this.$refs.tree.append(data, this.currentNode.parent)
},
增加子级节点事件
// 增加子级节点事件
addChildNode() {
console.log(this.currentData)
console.log(this.currentNode)
if (this.currentNode.level >= 3) {
this.$message.error('最多只支持三级!')
return false
}
let id = Math.ceil(Math.random() * 100)
var data = { id: id, label: '新增节点' }
this.$refs.tree.append(data, this.currentNode)
},
删除节点
// 删除节点
deleteNode() {
this.$refs.tree.remove(this.currentNode)
},
编辑节点
// 编辑节点
editNode(data) {
console.log(data)
this.currentData = data ? data : this.currentData
if (!this.currentData.isEdit) {
this.$set(this.currentData, 'isEdit', true)
}
// 获取焦点
this.$nextTick(() => {
this.$refs['slotTreeInput' + this.currentData.id].focus()
})
},
整体代码
<template>
<div class="tree-container">
<el-input placeholder="输入关键字进行过滤" v-model="filterText" class="search">
</el-input>
<el-tree :data="treeData" node-key="id" default-expand-all @node-click="handleLeftclick"
@node-drag-start="handleDragStart" @node-drag-enter="handleDragEnter" @node-drag-leave="handleDragLeave"
@node-drag-over="handleDragOver" @node-drag-end="handleDragEnd" @node-drop="handleDrop"
@node-contextmenu="rightClick" :filter-node-method="filterNode" draggable :allow-drop="allowDrop"
:allow-drag="allowDrag" ref="tree" class="tree-line">
<span class="slot-t-node" slot-scope="{ node, data }" @dblclick="editNode(data)">
<span v-show="!data.isEdit">
<span :class="[data.id >= 99 ? 'slot-t-node--label' : '']">
<i v-if="data.type == 'catalog'" class="el-icon-folder" />
<i v-if="data.type == 'menu'" class="el-icon-tickets" />
<i v-if="data.type == 'submenu'" class="el-icon-document" />
<span> {{ node.label }}</span>
</span>
</span>
<span v-show="data.isEdit">
<el-input class="slot-t-input" size="mini" autofocus v-model="data.label" :ref="'slotTreeInput' + data.id"
@blur.stop="NodeBlur(node, data)" @keydown.native.enter="NodeBlur(node, data)"></el-input>
</span>
</span>
</el-tree>
<!-- <el-card class="box-card" ref="card" v-show="menuVisible">
<div @click="addSameLevelNode()" v-show="firstLevel">
<i class="el-icon-circle-plus-outline"></i>&nbsp;&nbsp;同级增加
</div>
<div class="add" @click="addChildNode()">
<i class="el-icon-circle-plus-outline"></i> 子级增加
</div>
<div class="delete" @click="deleteNode()">
<i class="el-icon-remove-outline"></i> 删除节点
</div>
<div class="edit" @click="editNode()">
<i class="el-icon-edit"></i> 修改节点
</div>
</el-card> -->
<div class="box-menu" v-show="menuVisible" :style="{ left: menu_left + 'px', top: menu_top + 'px' }">
<div @click="addSameLevelNode(0)" v-show="firstLevel">
<i class="el-icon-circle-plus-outline"></i> 同级增加
</div>
<div class="add" @click="addChildNode()">
<i class="el-icon-circle-plus-outline"></i> 子级增加
</div>
<div class="delete" @click="deleteNode()">
<i class="el-icon-remove-outline"></i> 删除节点
</div>
<div class="edit" @click="editNode()">
<i class="el-icon-edit"></i> 修改节点
</div>
</div>
</div>
</template>
<script>
export default {
name: 'tree',
data() {
return {
eleId: '',
isShow: false,
currentData: '',
currentNode: '',
menuVisible: false,
firstLevel: false,
filterText: '',
maxexpandId: 4,
menu_left: 0,
menu_top: 0,
treeData: [{
id: 1,
label: '一级 1',
isEdit: false,
type: 'catalog',
children: [{
id: 4,
label: '二级 1-1',
isEdit: false,
type: 'menu',
children: [{
id: 9,
label: '三级 1-1-1',
isEdit: false,
type: 'submenu',
}, {
id: 10,
label: '三级 1-1-2',
isEdit: false,
type: 'submenu',
}]
}]
}, {
id: 2,
label: '一级 2',
isEdit: false,
type: 'catalog',
children: [{
id: 5,
label: '二级 2-1',
isEdit: false,
type: 'menu',
}, {
id: 6,
label: '二级 2-2',
isEdit: false,
type: 'menu',
}]
}, {
id: 3,
label: '一级 3',
isEdit: false,
type: 'catalog',
children: [{
id: 7,
label: '二级 3-1',
isEdit: false,
type: 'menu',
}, {
id: 8,
label: '二级 3-2',
isEdit: false,
type: 'menu',
children: [{
id: 11,
label: '三级 3-2-1',
isEdit: false,
type: 'submenu',
}, {
id: 12,
label: '三级 3-2-2',
isEdit: false,
type: 'submenu',
}, {
id: 13,
label: '三级 3-2-3',
isEdit: false,
type: 'submenu',
}]
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
}
},
methods: {
NodeBlur(Node, data) {
console.log(Node, data)
if (data.label.length === 0) {
this.$message.error('菜单名不可为空!')
return false
} else {
if (data.isEdit) {
this.$set(data, 'isEdit', false)
console.log(data.isEdit)
}
this.$nextTick(() => {
this.$refs['slotTreeInput' + data.id].$refs.input.focus()
})
}
},
// 查询
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
allowDrop(draggingNode, dropNode, type) {
if (dropNode.data.label === '二级 3-1') {
return type !== 'inner'
} else {
return true
}
},
allowDrag(draggingNode) {
return draggingNode.data.label.indexOf('三级 3-2-2') === -1
},
// 鼠标右击事件
rightClick(event, object, Node, element) {
console.log(event, object)
this.currentData = object
this.currentNode = Node
if (Node.level === 1) {
this.firstLevel = true
} else {
this.firstLevel = false
}
this.menuVisible = true
document.addEventListener('click', this.foo)
// 将菜单显示在鼠标点击旁边定位
this.menu_left = event.clientX -140;
this.menu_top = event.clientY - 40;
},
// 鼠标左击事件
handleLeftclick(data, node) {
this.foo()
},
// 取消鼠标监听事件 菜单栏
foo() {
this.menuVisible = false
// 要及时关掉监听,不关掉的是一个坑,不信你试试,虽然前台显示的时候没有啥毛病,加一个alert你就知道了
document.removeEventListener('click', this.foo)
},
// 增加同级节点事件
addSameLevelNode() {
let id = Math.ceil(Math.random() * 100)
var data = { id: id, label: '新增节点' }
this.$refs.tree.append(data, this.currentNode.parent)
},
// 增加子级节点事件
addChildNode() {
console.log(this.currentData)
console.log(this.currentNode)
if (this.currentNode.level >= 3) {
this.$message.error('最多只支持三级!')
return false
}
let id = Math.ceil(Math.random() * 100)
var data = { id: id, label: '新增节点' }
this.$refs.tree.append(data, this.currentNode)
},
// 删除节点
deleteNode() {
this.$refs.tree.remove(this.currentNode)
},
// 编辑节点
editNode(data) {
console.log(data)
this.currentData = data ? data : this.currentData
if (!this.currentData.isEdit) {
this.$set(this.currentData, 'isEdit', true)
}
// 获取焦点
this.$nextTick(() => {
this.$refs['slotTreeInput' + this.currentData.id].focus()
})
},
handleDragStart(node, ev) {
console.log('drag start', node)
},
handleDragEnter(draggingNode, dropNode, ev) {
console.log('tree drag enter: ', dropNode.label)
},
handleDragLeave(draggingNode, dropNode, ev) {
console.log('tree drag leave: ', dropNode.label)
},
handleDragOver(draggingNode, dropNode, ev) {
console.log('tree drag over: ', dropNode.label)
},
handleDragEnd(draggingNode, dropNode, dropType, ev) {
console.log('tree drag end: ', dropNode && dropNode.label, dropType)
},
handleDrop(draggingNode, dropNode, dropType, ev) {
console.log('tree drop: ', dropNode.label, dropType)
},
},
watch: {
filterText(val) {
this.$refs.tree.filter(val)
}
},
mounted() {
}
}
</script>
<style scoped lang="less">
.el-tree>.is-leaf {
color: transparent;
}
.tree-container /deep/ .el-tree-node__expand-icon.expanded {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
.tree-container /deep/ .el-tree-node__expand-icon.expanded {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
.tree-container /deep/ .el-icon-caret-right:before {
background: url("../../assets/node-collapse.png") no-repeat;
content: '';
display: block;
width: 12px;
height: 12px;
font-size: 12px;
background-size: 10px;
}
/*
//有子节点 且已展开*/
.tree-container /deep/ .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
background: url("../../assets/node-expand.png") no-repeat;
content: '';
display: block;
width: 12px;
height: 12px;
font-size: 12px;
background-size: 10px;
}
/* //没有子节点*/
.tree-container /deep/ .el-tree-node__expand-icon.is-leaf::before {
background: transparent no-repeat 0 3px;
content: '';
display: block;
width: 12px;
height: 12px;
font-size: 12px;
background-size: 10px;
}
/* 点击节点时的选中颜色 */
.tree-container /deep/.el-tree-node.is-current>.el-tree-node__content {
color: #3D5ECC !important;
}
.tree-container /deep/ .el-tree-node__expand-icon {
margin-left: 15px;
}
.tree-container /deep/ .el-tree-node__expand-icon.is-leaf {
margin-left: 0px;
}
.tree-container /deep/ .el-tree-node {
position: relative;
padding-left: 16px;
}
.tree-container /deep/ .el-tree-node__children {
padding-left: 16px;
}
.tree-container /deep/ .el-tree>.el-tree-node:before {
border-left: none;
}
.tree-container /deep/ .el-tree>.el-tree-node:after {
border-top: none;
}
.tree-container /deep/ .el-tree>.el-tree-node:before {
border-left: none;
}
.tree-container /deep/ .el-tree>.el-tree-node:after {
border-top: none;
}
.tree-container /deep/ .el-tree-node:before {
content: "";
left: 10px;
position: absolute;
right: auto;
border-width: 1px;
}
.tree-container /deep/ .el-tree-node:after {
content: "";
left: 10px;
position: absolute;
right: auto;
border-width: 1px;
}
.tree-container /deep/ .el-tree-node:before {
border-left: 1px dashed #ccc;
bottom: 0px;
height: 100%;
top: -19px;
width: 1px;
}
.tree-container /deep/ .el-tree-node:after {
border-top: 1px dashed #ccc;
height: 25px;
top: 20px;
width: 20px;
}
.el-tree-node :last-child:before {
height: 40px;
}
.tree-container {
margin: 10px;
}
.tree-container /deep/ .el-tree .el-tree-node {
position: relative;
}
.tree-container /deep/ .el-tree-node .el-tree-node__content {
height: 34px;
padding-left: 0px !important;
border: none;
}
.tree-container /deep/ .el-tree-node .el-tree-node__content::before {
border-left: 1px dashed #ccc;
height: 100%;
top: 0;
width: 1px;
margin-left: 1px;
margin-top: 0px;
z-index: 8;
}
.tree-container /deep/ .el-tree-node .el-tree-node__children .el-tree-node__content::before {
border-left: 0px dashed #ccc;
height: 100%;
top: 0;
width: 1px;
margin-left: 1px;
margin-top: 0px;
z-index: 8;
}
.tree-container /deep/ .el-tree-node .el-tree-node__content::after {
border-top: 1px dashed #ccc;
height: 1px;
top: 18px;
width: 13px;
margin-left: 1px;
z-index: 8;
}
.tree-container /deep/ .el-tree-node .el-tree-node__children .el-tree-node__content::after {
border-top: 0px dashed #ccc;
}
.tree-container .el-tree-node .el-tree-node__content::before,
.tree-container .el-tree-node .el-tree-node__content::after {
content: "";
position: absolute;
right: auto;
}
.el-tree {
width: 20%;
margin-top: 10px;
}
.search {
width: 20%;
}
.item {
padding: 18px 0;
}
.search {
cursor: pointer;
}
.box-menu {
width: 150px;
position: absolute;
z-index: 1000;
background-color: #fff;
box-shadow: 0px 0px 10px #ccc, 0px 0px 20px #ccc, 0px 0px 30px #ccc;
padding: 10px;
div {
cursor: pointer;
line-height: 30px;
}
div:active {
color: blue;
}
}
</style>
原文地址:https://blog.csdn.net/weixin_65635437/article/details/131312557
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_24856.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。