请教 transition-group 和 template 递归调用错误问题?

组件

const vpp = Vue.createApp(ListRendering);
    vpp.component('p-tree', {
        props: {
            items: Object,
            pi: String,
            deep: Number
        },
        template: `
          <transition-group name="list-complete">
          <template v-for="(item,i) in items">
            <li :class="'li-'+deep">{{ pi + (i + 1) + ' . ' + item.title }}</li>
            <p-tree v-if="item.child.length > 0" :pi="pi+(i+1)+'-'" :deep="++deep" :items="item.child"></p-tree>
          </template>
          </transition-group>`

    });
    const app = vpp.mount('#list-rendering');

我是想在树有节点变化的时候有个过渡动效,添加 transition-group 组件 反而导致渲染都渲染不了了。求大神解答

下面是一个完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.7/vue.global.prod.js"></script>
    <style>
        ul, li {margin:0;padding:0; list-style:none; line-height:2.2; font-size:14px; transition:all 0.8s ease;}

        li:nth-child(even) {background:#f1f1f1;}

        li:hover {background-color:#dfe5ee;}

        li.li-1 {padding-left:20px;}

        li.li-2 {padding-left:40px;}

        li.li-3 {padding-left:60px;}

        li.li-4 {padding-left:80px;}

        li.li-5 {padding-left:100px;}

        .list-complete-enter-from,
        .list-complete-leave-to {
            opacity:0;
            transform:translateY(30px);
        }

        .list-complete-leave-active {
            position:absolute;
        }


    </style>
</head>
<body>
<div id="list-rendering">
    <ul>
        <p-tree deep="1" :items="child" pi=""></p-tree>
    </ul>
</div>

<script>
    const ListRendering = {
        data() {
            return {
                child: [
                    {
                        title: 'titless',
                        child: []
                    },
                    {
                        title: 'titlee',
                        child: [
                            {
                                title: 'titqer1',
                                child: []
                            },
                            {
                                title: 'titl111',
                                child: []
                            }
                        ]
                    },
                    {
                        title: 'hhhh 3',
                        child: [
                            {
                                title: 'hhhh',
                                child: []
                            }
                        ]
                    }
                ]
            };
        },
        methods: {}
    }
    const vpp = Vue.createApp(ListRendering);
    vpp.component('p-tree', {
        props: {
            items: Object,
            pi: String,
            deep: Number
        },
        template: `
          <transition-group name="list-complete">
          <template v-for="(item,i) in items">
            <li :class="'li-'+deep">{{ pi + (i + 1) + ' . ' + item.title }}</li>
            <p-tree v-if="item.child.length > 0" :pi="pi+(i+1)+'-'" :deep="++deep" :items="item.child"></p-tree>
          </template>
          </transition-group>`

    });
    const app = vpp.mount('#list-rendering');


    /**
     * 调用 changeDataByTab 方法希望界面上能有动画效果
     */

    // 增加
    ['dsf', 'fff', 'rrr', 'reee'].forEach(v => app.$data.child[1].child.push({title: v, child: []}));

    // 左退格
    // changeDataByTab('1-4', 1);
    // changeDataByTab('1-4', 1);
    // changeDataByTab('1-3-1', 1);

    // 右退格
    // changeDataByTab('1-1',-1);

    function changeDataByTab(index, d) {
        let data = app.$data;
        let ar = index.split('-').map(v => parseInt(v));
        let l = ar.length - (d > 0 ? 1 : 2);
        for (let i = 0; i < l; i++) {
            data = data.child[ar[i]];
        }
        let k = ar[l];
        if (d > 0) {
            if (k === 0) {
                return false;
            } else if (k > 0) {
                let tmp = data.child[k];
                if (typeof tmp === 'undefined') {
                    console.warn('索引不存在 001', index);
                    return false;
                }
                data.child[k - 1].child.push(tmp);
                data.child.splice(k, 1);
            } else {
                console.warn('异常数据 002', index);
            }
        } else if (l > -1) {
            let k = ar[l];
            let k1 = ar[l + 1];
            let tmp = data.child[k].child[k1];
            if (typeof tmp === 'undefined') {
                console.warn('索引不存在 004', index);
                return false;
            }
            data.child[k].child.splice(k1, 1);
            data.child.splice(k + 1, 0, tmp);
        } else {
            console.warn('异常数据 003', index, d);
        }
    }
</script>
</body>
</html>
阅读 1.5k
2 个回答

应该是li和p-tree放在同一层的问题,改成这样试试

const vpp = Vue.createApp(ListRendering);
    vpp.component('p-tree', {
        props: {
            items: Object,
            pi: String,
            deep: Number
        },
        template: `
          <transition-group name="list-complete">
          <template v-for="(item,i) in items">
            <li :class="'li-'+deep">
            <div>{{ pi + (i + 1) + ' . ' + item.title }}</div>
             <ul>
             <p-tree v-if="item.child.length > 0" :pi="pi+(i+1)+'-'" :deep="++deep" :items="item.child"></p-tree>
             </ul>
            </li>
          </template>
          </transition-group>`

    });
    const app = vpp.mount('#list-rendering');

有没有报什么明显的错误?
目前发现你的代码中v-for缺少key, 和:deep="++deep" 应该写成:deep="deep+1",deep通过props传进来的不允许修改

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏