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>
                    
                
                
            
        
浙公网安备 33010602011771号