怎么把v-for的渲染频率降低到最低?提供五种方案!

最近在写聊天工具的会话列表部分,发现一个问题,当会话出现频繁更新的时候,会让列表渲染的非常频繁。

虽然影响很小,但是做一流工具的态度还是要有的,所以研究研究怎么把v-for的渲染更新频率降低。

在vue中,使用v-for指令进行渲染的时候,vue会尽可能重用现有的DOM元素,而不是每次全部重新渲染,这就是 就地更新 。

<template v-for="talk in talkList">
  <component :is="talk.sendUserId === selfId ? 'MeMsg' : 'OtherMsg'" :msg-record="talk"></component>
</template>

上述代码当 talkList 出现 push 新对象的时候,被循环的动态组件就会发生重新渲染,想要尽可能降低渲染次数的方法有几种。

1. 给列表项一个唯一的key

为每个列表项绑定一个唯一的key属性,vue框架能够高效的识别出是哪个项发生了修改,只重现渲染特定的项,而不会出现全部项重新渲染。

<template v-for="talk in talkList" :key="talk.id">
  <component :is="talk.sendUserId === selfId ? 'MeMsg' : 'OtherMsg'" :msg-record="talk"></component>
</template>

2. 通过对象的响应性更新

当数组中列表项出现增删的时候,如果数组是在data中定义的,那么 talkList 数组和内部对象也会变成响应式的,当出现更新的时候列表项也会随之重新渲染。

// 新增
this.talkList.push({ id3sendUserId'user3'message'Another message' });
this.talkList.unshift({ id3sendUserId'user3'message'Another message' });
// 替换
this.talkList.splice(index, 1, { id1sendUserId'user1'message'Replaced message' });

如果需要向 talkList 动态添加新属性,或者更新对象中现有的属性,并确保其响应性,可以通过 $set 方法更新。

// 假设你想更新id为1的对象的消息内容
let index = this.talkList.findIndex(talk => talk.id === 1);
if (index !== -1) {
  // 使用this.$set确保更改是响应式的
  this.$set(this.talkList[index], 'message''Updated message');
}

3. 通过生命周期钩子

export default {
  props: ["msgRecord"],
  beforeUpdate(){
    // 判断是否发生更新,没有变化可以阻止更新
  },
  watch: {
    msgRecord(newVal, oldVal){
      // 根据数据变化的情况决定是否更新
    }
  }
}

4. 使用keep-alive缓存

如果出现频繁的显隐操作可以使用 keep-alive 包裹列表项,将列表项状态进行缓存,显示时就不会再重新渲染。(与当前需求不符合,只是提供一种思路)

5. 使用v-memo指令

在 vue3 中存在一个新的指令 v-memo,通过该指令判断当数据发生变化时才重新渲染该组件。(这是性价比最高的一种方案)

<template v-for="talk in talkList" :key="talk.id" v-memo="[talk]">
  <component :is="talk.sendUserId === selfId ? 'MeMsg' : 'OtherMsg'" :msg-record="talk"></component>
</template>

结论

综上,如果在 vue2 中,性能要求不是非常“BT”的情况下,直接绑定 key 即可,有要求可以考虑使用生命周期钩子进行操作。vue3中直接无脑上 v-memo 即可。

原文链接:https://juejin.cn/post/7457551678210326582 作者:李剑一

(0)
上一篇 2025年1月4日 下午4:00

相关推荐

发表回复

登录后才能评论