tree 动态添加、删除树结构数据
tree.vue 组件
<template> <div> <div @click="getData" :style="getDetph(currentItem.level)" class="li"> <span class="icon"></span> <div contenteditable class="edit" :class="'input' + currentItem.id" @keydown="textareaKeydown($event, currentItem, itemIndex)">{{ currentItem.id }}</div> </div> <div v-if="isShow"> <tree :currentItem="item" :itemIndex="index" v-for="(item, index) in currentItem.children" @insert="insert" @delete="deleteFun" :key="index"> </tree> </div> </div> </template> <script> export default { name: "tree", components: {}, data: function () { return { isShow: true }; }, props: { // 接收标题 currentItem: { type: Object // default: "标题" }, itemIndex: { type: Number } }, methods: { getDetph(level) { return `transform:translate(${level * 20}px)`; }, insert(obj){ this.$emit('insert', obj) }, deleteFun(obj){ this.$emit('delete', obj) }, getData: function () { this.isShow = true }, textareaKeydown(event, currentItem, index) { console.log(event.target.innerText) if (event.keyCode === 13) { this.$emit('insert', { parentId: currentItem.parentId, level: currentItem.level }); event.preventDefault() // 阻止浏览器默认换行操作 return false } else if (event.key =="Backspace" && !event.target.innerText) { this.$emit('delete', { parentId: currentItem.parentId, level: currentItem.level, index }); event.preventDefault() // 阻止浏览器默认换行操作 return false } else if (event.keyCode === 9 && event.target.innerText) { this.$emit('insert', { parentId: currentItem.id, level: currentItem.level + 1 }); event.preventDefault() // 阻止浏览器默认换行操作 return false } else if (event.keyCode === 9 && !event.target.innerText) { event.preventDefault() // 阻止浏览器默认换行操作 return false } }, } }; </script> <style scoped> /* @import url(); 引入css类 */ .li{ width: 100%; height: 30px; line-height: 30px; } .edit{ width: calc(100% - 16px); float: left; margin-left: 10px; } .edit:focus{ border:none; outline: none; } .icon{ display: inline-block; height: 6px; width: 6px; border-radius: 50%; background: #000; float: left; margin-top: 10px; } </style>
父组件
<template> <div class="home"> <div > <tree v-for="(item, index) in list" :key="index" :currentItem="item" @insert="insert" @delete="deleteFun" :itemIndex="index"></tree> </div> </div> </template> <script> import tree from '../components/tree' export default { name: "Home", components: { tree }, data: function () { return { list: [{ id: 0, name: "标题", level: 0, children:[{ id: 1 + '-' + 0, name: "酒店", level: 1, parentId: 0, children: [] }] }] }; }, methods: { deleChildFun(arr, obj){ arr.forEach(item=>{ if(item.id == obj.parentId){ console.log('obj.index', obj.index) const preItem = obj.index> 0 ? item.children[obj.index -1] : item console.log('preItem', preItem) item.children.splice(obj.index, 1) this.$nextTick(() => { const notesDom = document.getElementsByClassName('input' + preItem.id)[0] this.setRang(notesDom) }) } if(item.children && item.children.length > 0){ this.deleChildFun(item.children, obj) } }) }, deleteFun(obj){ this.deleChildFun(this.list, obj) console.log(this.list) }, insertChildren(list, obj){ list.forEach(item=>{ if(item.id == obj.parentId){ const length = item.children.length item.children.push({ id: obj.parentId + '-' + obj.level + '-' + length, name: '', parentId: obj.parentId, level: obj.level, children: [] }) this.$nextTick(() => { const notesDom = document.getElementsByClassName('input' + obj.parentId + '-' + obj.level + '-' + length)[0] console.log('input', notesDom) this.setRang(notesDom) }) } if(item.children && item.children.length > 0){ this.insertChildren(item.children, obj) } }) }, insert (obj) { this.insertChildren(this.list, obj) console.log(this.list) }, setRang(notesDom){ if (window.getSelection) { // 兼容 IE11 10 9 ff safari // notesDom.focus(); // 解决ff不获取焦点无法定位问题 let range = window.getSelection(); // 创建range range.selectAllChildren(notesDom); // range 选择notesDom下所有子内容 range.collapseToEnd(); // 光标移至最后 } else if (document.selection) { // 兼容 IE10 9 8 7 6 let range = document.selection.createRange(); // 创建选择对象 range.moveToElementText(notesDom); // range定位到notesDom range.collapse(false); // 光标移至最后 range.select(); } } } }; </script> <style scoped> .ww { margin-left: 20px; } .hh { font-size: 10px; } </style>