3

如果你是想看怎么做?那么你可以直接去看我之前写的Vue 实现弹幕效果

正好这段时间内部在抽离常用组件,运营小姐姐最近迷上了飘屏功能,各种活动都要有个飘屏才罢休。然后就安排人抽离成组件了。
结果这个组件在同一个位置绊倒了两个人,那么今天我们来分析一下。

复现BUG

BUG复现地址:https://www.lilnong.top/static/html/vue-bug-bullet.1.html
BUG修复地址:https://www.lilnong.top/static/html/vue-bug-bullet.2.html
BUG对比地址:https://www.lilnong.top/static/html/vue-bug-bullet.3.html

image.png

可以直接查看对比地址,会发现左边的动画异常闪动而且 DOM 没有被移除

弹幕逻辑

  1. 一秒 push 一条数据。
  2. 五条通道循环
  3. 动画 7s, animationend 事件移除第一个

分析问题

  1. 第一步,我们先排查逻辑,看看是否因为移除的时候不对,造成了数据错乱。可以看到我们是 shift,基于我们的定长动画,肯定是第一个先执行完成。

    animationend(){
         this.list.push(this.bulletlist.shift())
    },
    .bullet-animation{animation: right2left 7s linear both;}
  2. 经过我们的观察,像是动画突然换行,并且前进了。然后我们打开控制台直接查看 DOM,发现是所有的内容改变,并不是 DOM 节点改变
    image.png
  3. 到了这个我们可以分析出了问题,DOM 被复用了,因为动画是作用在 DOM 上的,当前 DOM 的动画已经完成了。

    那么 Vue 的 DOM 复用规则是什么呢?

    https://cn.vuejs.org/v2/guide/list.html
    当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
    https://cn.vuejs.org/v2/api/#key
    image.png
  4. 通过上面的文档,我们可以看到,提供一个合理的 key 就可以强制渲染 DOM,可以触发过渡。那么我们就查看一下 key 设置的什么呢?:key="idx"
    看来我们找到了问题,因为 idx 和 item 其实没有固定的对应关系的,所以 DOM 被复用了,应该使用 :key="item.id"

总结

让我们遇事不决,量子力学一哈。

  1. 在 Vue 中使用 v-for 应该搭配一个 :key 来使用。
  2. :key 需要是一个唯一值,比如 id。最好不要用 index。
  3. 如果需要强制更新 DOM,我们可以使用 :key 来告诉 Vue 引擎这是两个不同的元素。

相似问题

有的人可能会说,为什么我也用了下标为什么没有报错呢?

其实还有挺多相似问题的,核心点就是有没有进行过修改

  1. 比如说有排序移动,如果没有提供一个合理的 key,那么就会乱套
  2. 两个结构相似,但是没有使用 v-for,切换隐藏显示的时候。

微信公众号:前端linong

clipboard.png


linong
29.2k 声望9.5k 粉丝

Read-Search-Ask