怎么把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({ id: 3, sendUserId: 'user3', message: 'Another message' });
this.talkList.unshift({ id: 3, sendUserId: 'user3', message: 'Another message' });
// 替换
this.talkList.splice(index, 1, { id: 1, sendUserId: '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 即可。

JavaScript高阶面试-323问

1.不会冒泡的事件有哪些?

2.mouseEnter 和 mouseOver 有什么区别?

3.MessageChannel 是什么,有什么使用场景?

4.async、await 实现原理

5.Proxy 能够监听到对象中的对象的引用吗?

6.如何让 var 「a, b]= {a: 1,b:2}解构赋值成功?

7.下面代码会输出什么?

8.描述下列代码的执行结果

9.什么是作用域链?

10.bind、call、apply 有什么区别?如何实现一个bind?

11.common.js和es6中模块引入的区别?

12.说说 vue3 中的响应式设计原理

13.soript标签放在header里和放在body底部里有什么区别?

14.下面代码中,点击“+3"按钮后,age 的值是什么?

15.Vue中,created和mounted两个钩子之间调用时间差值受什么影响?

16.vue中,推荐在哪个生命周期发起请求?

17.不会冒泡的事件有哪些?

18.mouseEnter 和 mouseOver 有什么区别?

19.为什么Node在使用es module时必须加上文件扩展名?

20.package.json 文件中的 devDependencies 和 dependencies 对象有什么区别?

……

313.改造下面的代码,让它输出1,2,3,4,5

314.Object.is和===有什么区别?

315.instanceof能否判断基本数据类型?

316.typeof 是否能正确判断类型?

317.什么是BigInt?

318.0.1+0.2为什么不等于0.3?

319.'1'.toString()为什么不会报错?

320.null是对象吗?为什么?

321.什么是内存泄漏?什么原因会导致呢?

322.webSocket如何兼容低浏览器

323.什么是跨域?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值