先上代码
<template>
<div>
<template v-slot:content>
<Tree :data="data5" :render="renderContent"></Tree>
</template>
<template v-slot:footer></template>
</div>
</template>
<script>
export default {
name: 'drawer-oepn-menu',
props: {
show: {
type: Boolean,
default: false
}
},
data() {
return {
editState: false,
data5: [
{
id: null,
title: '全部',
expand: true,
// eslint-disable-next-line no-unused-vars
render: (h, { root, node, data }) => {
return h('span', {
style: {
display: 'inline-block',
width: '100%'
}
}, [
h('span', [
h( "span", data.title)
])
]);
},
children: [
{
id: 1,
title: '子',
expand: true
},
{
id: 2,
title: '子2',
expand: true
}
]
}
],
buttonProps: {
type: 'default',
size: 'small'
},
// 输入框要修改的内容
inputContent: "",
// 修改前的TreeNode名称
oldName: ""
}
},
methods: {
handleClose() {
this.$emit('close')
},
// 树渲染逻辑
renderContent(h, { root, node, data }) {
return h("span", {
class: "menu-tree",
style: {
display: 'inline-block',
lineHeight: '1.6rem',
width: '100%',
cursor: 'pointer'
},
on: {
click: () => {
// 点击Tree节点触发
data.editState ? '' : this.handleClickTreeNode(data)
}
}
}, [
h('span', [
h(`${data.editState ? '' : 'span'}`, data.title),
// 使用this.$createElement创建的节点可以获取到$ref,避免使用h无法获取到的bug
this.$createElement(`${data.editState ? 'Input' : ''}`,
{
attrs: {
value: `${data.editState ? data.title : ''}`,
autofocus: true
},
ref: 'slotTreeInput' + data.id,
style: {
width: '12rem',
cursor: 'auto'
},
on: {
'on-change': (event) => {
this.inputContent = event.target.value
},
'on-blur': () => {
this.confirmTheChange(data)
},
// eslint-disable-next-line no-undef
'on-enter': (event) => {
event.target.blur()
}
}
}
)
]),
// 增删改按钮部分
h(`${data.editState ? '' : 'span'}`,
{
class: "btnNone",
style: { marginLeft: '1rem' }
},
[
//操作按钮部分
// 编辑按钮
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-brush-outline'
}),
style: {
marginRight: '8px',
borderRadius: '50%',
width: '1.5rem',
lineHeight: '0',
padding: '0',
height: '1.4rem'
},
on: {
click: () => { this.editTree(data) }
}
}),
// 添加按钮
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-add'
}),
style: {
marginRight: '8px',
borderRadius: '50%',
width: '1.5rem',
lineHeight: '0',
padding: '0',
height: '1.4rem'
},
on: {
click: () => { this.append(data) }
}
}),
// 删除按钮
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-remove'
}),
style: {
marginRight: '8px',
borderRadius: '50%',
width: '1.5rem',
padding: '0',
lineHeight: '0',
height: '1.4rem'
},
on: {
click: () => { this.remove(root, node, data) }
}
})
]
),
// 确认/取消修改部分
h(`${data.editState ? 'span' : ''}`,
{
style: {
marginLeft: '.5rem'
}
},
[
// 确认按钮
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'md-checkmark'
}),
style: {
// marginRight: '8px',
border: 0,
background: 'rgba(0,0,0,0)',
fontSize: '1.3rem',
outline: "none"
},
on: {
click: () => {
this.confirmTheChange(data)
}
}
}),
// 取消按钮
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'md-close'
}),
style: {
border: '0',
background: 'rgba(0,0,0,0)',
fontSize: '1.3rem',
outline: "none"
},
on: {
click: () => { this.CancelChange(data) }
}
})
]
)
]);
},
// 控制Tree当前状态函数
setStates(data) {
var editState = data.editState
if (editState) {
this.$set(data, 'editState', false);
} else {
this.$set(data, 'editState', true);
this.$nextTick(() => {
if (this.$refs['slotTreeInput' + data.id]) {
this.$refs['slotTreeInput' + data.id].focus()
}
})
}
},
// Tree修改按钮
editTree(data) {
event.stopPropagation()
this.inputContent = data.title
this.oldName = data.title
this.setStates(data)
},
// 添加按钮
append(data) {
event.stopPropagation()
const children = data.children || [];
children.push({
title: '新建节点',
expand: true
});
this.$set(data, 'children', children);
},
// 删除按钮
remove(root, node, data) {
event.stopPropagation()
this.$Modal.confirm({
title: "提示",
content: `您确定删除 “${data.title}” 吗?`,
onOk: () => {
const parentKey = root.find(el => el === node).parent;
const parent = root.find(el => el.nodeKey === parentKey).node;
const index = parent.children.indexOf(data);
parent.children.splice(index, 1);
this.$Message.info('删除成功');
},
onCancel: () => {
this.$Message.info('取消');
}
});
},
// 确认修改树节点
confirmTheChange(data) {
if (!this.inputContent) {
this.$Notice.warning({
title: '当前输入有误'
});
} else {
data.title = this.inputContent
this.setStates(data);
}
},
// 取消修改树节点
CancelChange(data) {
this.$Notice.info({
title: '取消修改'
});
this.setStates(data)
},
// 点击Tree节点触发
handleClickTreeNode(data) {
console.log("当前点击》》" + data.title)
}
}
}
</script>
<style >
.IviewTree{
width: 300px;
text-align: left;
margin: 0 auto;
}
.btnNone{
display:none
}
/* .menu-tree:hover{color:aqua} */
.menu-tree:hover .btnNone{
display: inline-block
}
.menu-tree:hover {
font-weight: 600;
color:#275cd4
}
.ivu-tree ul li {
list-style: none;
/* margin: 8px 0; */
padding: 0;
white-space: nowrap;
outline: none;
}
</style>
最终所需要的效果图
<template>
<div>
<template v-slot:content>
<Button @click="append" v-if="data5[0].children.length < 29">添加</Button>
<Tree :data="data5" :render="renderContent"></Tree>
</template>
<template v-slot:footer></template>
</div>
</template>
<script>
export default {
name: 'drawer-oepn-menu',
props: {
show: {
type: Boolean,
default: false
}
},
data() {
return {
editState: false,
NODE_ID_START: 100,
startId: null,
data5: [
{
id: null,
title: '全部',
expand: true,
// eslint-disable-next-line no-unused-vars
render: (h, { root, node, data }) => {
return h('span', {
style: {
display: 'inline-block',
width: '100%'
}
}, [
h('span', [
h( "span", data.title)
])
]);
},
children: [
{
id: null,
title: 'default',
expand: true
}
]
}
],
buttonProps: {
type: 'default',
size: 'small'
},
// 输入框要修改的内容
inputContent: "",
// 修改前的TreeNode名称
oldName: ""
}
},
watch: {
show (val) {
if (!val) { return }
this.startId = this.NODE_ID_START
}
},
methods: {
handleClose() {
this.$emit('close')
},
// 树渲染逻辑
renderContent(h, { root, node, data }) {
return h("span", {
class: "menu-tree",
style: {
display: 'flex',
lineHeight: '1.6rem',
width: '100%',
cursor: 'pointer',
'min-width': '100px',
'min-height': '20px',
'justify-content': 'space-between'
},
on: {
click: () => {
// 点击Tree节点触发
this.handleClickTreeNode(data)
}
}
}, [
h('span', [
h(`${data.editState ? '' : 'span'}`, data.title),
// 使用this.$createElement创建的节点可以获取到$ref,避免使用h无法获取到的bug
this.$createElement(`${data.editState ? 'Input' : ''}`,
{
'class': {
'err-input': data.title.length < 2 || data.title.length > 15
},
attrs: {
value: `${data.editState ? data.title : ''}`,
autofocus: true,
placeholder: this.$t('2~15位字符')
},
ref: 'slotTreeInput' + data.id,
style: {
width: '12rem',
cursor: 'auto'
},
on: {
'on-change': (event) => {
this.handleInputChange(event, data)
},
'on-blur': () => {
this.confirmTheChange(data)
},
// eslint-disable-next-line no-undef
'on-enter': (event) => {
event.target.blur()
}
}
}
)
]),
// default教室只允许编辑
h(`${!data.editState && data.id === null ? 'span' : ''}`, {
class: "btnNone",
style: { marginLeft: '1px' }
}, [
//操作按钮部分
// 编辑按钮
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-brush-outline'
}),
style: {
marginRight: '8px',
borderRadius: '50%',
width: '1.5rem',
lineHeight: '0',
padding: '0',
height: '1.4rem'
},
on: {
click: () => { this.editTree(data) }
}
})
]),
// 增删改按钮部分
h(`${!data.editState && data.id !== null ? 'span' : ''}`, {
class: "btnNone",
style: { marginLeft: '1rem' }
}, [
//操作按钮部分
// 编辑按钮
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-brush-outline'
}),
style: {
marginRight: '8px',
borderRadius: '50%',
width: '1.5rem',
lineHeight: '0',
padding: '0',
height: '1.4rem'
},
on: {
click: () => { this.editTree(data) }
}
}),
// 删除按钮
h('Button', {
props: Object.assign({}, this.buttonProps, {
icon: 'ios-remove'
}),
style: {
marginRight: '8px',
borderRadius: '50%',
width: '1.5rem',
padding: '0',
lineHeight: '0',
height: '1.4rem'
},
on: {
click: () => { this.remove(root, node, data) }
}
})
])
]);
},
// 控制Tree当前状态函数
setStates(data) {
var editState = data.editState
if (editState) {
this.$set(data, 'editState', false);
} else {
this.$set(data, 'editState', true);
this.$nextTick(() => {
if (this.$refs['slotTreeInput' + data.id]) {
this.$refs['slotTreeInput' + data.id].focus()
}
})
}
},
// Tree修改按钮
editTree(data) {
event.stopPropagation()
this.inputContent = data.title
this.oldName = data.title
this.setStates(data)
},
// 添加按钮
append() {
event.stopPropagation()
this.oldName = ''
let children = this.data5[0].children
let data = {
title: '',
id: ++this.startId,
expand: true
}
children.push(data);
this.setStates(data)
// this.$set(data, 'children', children);
},
// 删除按钮
remove(root, node, data) {
event.stopPropagation()
this.$Modal.confirm({
content: `确定删除目录吗,如果改目录下有开放的模板,则该目录下的所有模板将移入${this.data5[0].children[0].title}目录`,
loading: true,
onOk: () => {
setTimeout(() => {
const parentKey = root.find(el => el === node).parent;
const parent = root.find(el => el.nodeKey === parentKey).node;
const index = parent.children.indexOf(data);
parent.children.splice(index, 1);
this.$Modal.remove();
}, 1000);
}
});
},
// 确认修改树节点
confirmTheChange(data) {
console.log(this.oldName)
if (this.inputContent.length > 15 || (this.inputContent.length > 0 && this.inputContent.length < 2)) { return }
let arr = this.data5[0].children.map(item => item.title)
if (arr.findIndex(x => x === this.inputContent) !== -1 && this.inputContent !== this.oldName) {
return this.$Notice.open({
title: '目录已存在',
desc: '',
duration: 0
});
}
if (!this.inputContent && this.oldName.length === 0) {
this.data5[0].children.splice(this.data5[0].children.findIndex(x => x.title === ''), 1)
} else if (!this.inputContent && this.oldName) {
return
} else {
data.title = this.inputContent
this.setStates(data);
}
this.inputContent = ''
this.oldName = ''
},
// 点击Tree节点触发
handleClickTreeNode(data) {
console.log("当前点击》》" + data.title)
this.oldName = data.title
},
handleInputChange(e, data) {
console.log(data.title)
this.inputContent = event.target.value.replace(/\s*/g, "")
if (this.inputContent.length < 2 || this.inputContent.length > 15) {
event.target.classList.add('err-input')
} else {
event.target.classList.remove('err-input')
}
}
}
}
</script>
<style>
.IviewTree{
width: 300px;
text-align: left;
margin: 0 auto;
}
.btnNone{
display:none
}
/* .menu-tree:hover{color:aqua} */
.menu-tree:hover .btnNone{
display: inline-block
}
.menu-tree:hover {
font-weight: 600;
color:#275cd4
}
.ivu-tree ul li {
list-style: none;
/* margin: 8px 0; */
padding: 0;
white-space: nowrap;
outline: none;
}
.err-input.ivu-input {
border: 1px solid red;
}
</style>