有BUG

有BUG

问题描述:

为什么我删除一个元素之后,再点击增加,并没有从列表的头部增加?

相关代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>列表动画</title>
        <style>
            .v-enter-from {
                opacity: 0;
                transform: translateY(30px);
            }
            .v-enter-active,
            .v-leave-active {
                transition: all 0.5s ease-in;
            }
            .v-leave-active {
                position: absolute;
            }
            .v-enter-to {
                opacity: 1;
                transform: translateY(0);
            }
            .v-leave-to {
                opacity: 0;
                transform: translateY(-30px);
            }
            .v-move {
                transition: all 0.5s ease-in;
            }
            .list-item {
                display: inline-block;
                margin-right: 10px;
            }
        </style>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
        <div id="root"></div>
    </body>
    <script>
        const app = Vue.createApp({
            data() {
                return {
                    list: [3, 2, 1],
                };
            },
            methods: {
                handleClick() {
                    this.list.unshift(this.list.length + 1);
                },
                handleDel(index) {
                    this.list.splice(index, 1);
                },
            },
            template: `
                <div>
                    <transition-group>
                        <span 
                        class="list-item" 
                        v-for="(item,index) in list" 
                        :key="item" 
                        :dataindex="index" 
                        @click="handleDel(index)">
                            {{item}}
                        </span>
                    </transition-group>
                    <br>
                    <br>
                    <br>
                    <br>
                    <button @click="handleClick">增加</button>
                </div>
                `,
        });

        const vm = app.mount("#root");
    </script>
</html>

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
好帮手慕小李 2022-06-16 19:23:28

同学你好,这里出现bug的原因是因为this.list.splice(index, 1);改变了原来数组的长度,也就是说这里就点击删除后返回的是新的数组长度,那么我们在做增加的时候this.list.unshift(this.list.length + 1);数组的长度也发生了改变所导致的。如下:

https://img1.sycdn.imooc.com//climg/62ab0f90091131ed07830328.jpg

实际效果如下:

https://img1.sycdn.imooc.com//climg/62ab0ff6093ec09108970231.jpg

那么也就是说list的长度一直发生改变。所以在点击删除后再添加时就会有问题。

优化建议如下:

既然更改原数组的长度会发生问题,那么我们尝试在添加时更改原有数组,在删除时我们不操作原来的数组,那么就可以解决这个问题了。如下:

https://img1.sycdn.imooc.com//climg/62ab121b091d3d6008130464.jpg

js部分如下:

https://img1.sycdn.imooc.com//climg/62ab124509705c5907890375.jpg

效果如下:

https://img1.sycdn.imooc.com//climg/62ab12780962f03608280212.jpg

https://img1.sycdn.imooc.com//climg/62ab128e094e8db908930253.jpg

同学试试,祝学习愉快!

  • 提问者 CHENBIN_No1 #1

    这个方法可以解决上述问题,但是使用这个方法之后又有了新的BUG。

    1、当删除数组头部元素之后,再点击增加按钮之后就会出现以下错误,但是如果将unshift换成push,怎么删除都不会报错,这是什么原因呢,unshift和push有其他什么区别吗?

    https://img1.sycdn.imooc.com//climg/62ab4358095d44e211920268.jpg

    2、点击删除时,过渡和动画类没有被添加到DOM上。

    2022-06-16 22:51:28
  • 好帮手慕小李 回复 提问者 CHENBIN_No1 #2

    同学你好,解答如下:

    *注解释中第三点是针对这个练习的拓展,同学可以参考老师的思路。

    1、确实会发生这样的问题,这是因为使用e.target.remove()是直接删除的是dom,而并非是数据,那么如果直接删除下标为0项时,所以再次点击的增加的时候unshift会发现剩下的dom中的dataindex在更新并且数据还在更新,这里同学可以打印一下看看。如下:

    https://img1.sycdn.imooc.com//climg/62ab5ed509ebea3421760587.jpg

    当删除3时效果如下:

    https://img1.sycdn.imooc.com//climg/62ab5f3c09fa553d16010568.jpg

    当点击增加时效果如下:

    https://img1.sycdn.imooc.com//climg/62ab5f8709415ae229041695.jpg

    https://img1.sycdn.imooc.com//climg/62ab5fcc09fa7def15490519.jpg

    这里确实是一个坑,其中原因是unshift需要找到最前面的一项然后插入到第一项前,这条路走不通。

    那么同学提到了换成push以后就ok了,这是因为push是往数组最后一项进行插入但是它不需要去找到最后一项直接就会去插入到后面去,它与unshift不同,unshift是向最前面的一项前进行插入但是unshift需要找到第一项然后在第一项前进行插入。所以使用push就不会出现问题。

    2、当点击删除时发现确实动画效果没有了,这是因为我们直接做的是删除dom的操作,并没有更改list数据,就像我前面所说,list的长度并没有发生改变且list整体也并没有发生改变,在数据没有发生变化的时候vue则不会进行更新,这是vue的diff算法后面课程中会有讲到,这里就不做扩展了。

    3、针对以上的问题同学可以参考如下方案:

    首先我们确定了当添加的时候需要改变数组,当删除的时候不能修改数组为前提,且也不能直接删掉虚拟dom,删除操作时使用delete的方法刚好能满足需求:

    https://img1.sycdn.imooc.com//climg/62ab64ee099dcf4323260402.jpg

    https://img1.sycdn.imooc.com//climg/62ab654a09ee400216920450.jpg

    我们进行观察发现,使用delete的方法删除了2,它的(虚拟)dom元素还在,只不过innerHTML是空,但是空出来的位置还占着。

    那么我们可以借助v-show的方法让innerHTML为空的(虚拟)dom进行隐藏。如下:

    https://img1.sycdn.imooc.com//climg/62ab667309691e4d16961078.jpg

    最终效果如下:

    https://img1.sycdn.imooc.com//climg/62ab66a70967932f18470722.jpg

    这个练习实现方式不唯一,另老师在视频中也没有明确具体需求是什么,所以老师这里先给出一个解决方案,仅供同学参考。

    同学试试,祝学习愉快!

    2022-06-17 01:22:48
  • 你好老师,看了这位同学的问题,自己照着老师的例子试了一下,有两个问题想问一下

    1:如果不给span标签包裹一个父级标签就会报警告:<TransitionGroup> children must be keyed.

    然后网上查资料,发现需要添加key值,然后自己随便添加了一个<div key="item">.不知道这里的key值具体应该时什么值?

    2:这里使用delete删除保留dom节点,如果平凡操作会留下一堆没有值的节点对性能是不是一种很大的消耗?


    2023-06-04 14:58:15
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师