Vue.js v-model绑定输入卡顿 页面存在大量列表渲染项时如何解决?
问题根因
这个卡顿不是Vue的元素数量限制导致的,是同一个组件内的响应式更新触发了不必要的全量重渲染导致的:
- 你的表单
form对象和列表数据appKeys在同一个Vue组件实例下,每次修改form.description触发响应式更新时,整个组件的渲染函数会重新执行,下方130个列表项都会完整走一遍diff比对流程 - 模板中使用的
formatDate、formatDateTime过滤器没有缓存,每次重渲染都会对所有列表项的日期字段重新执行格式化计算,130个条目单次更新就会触发数百次函数调用 - 你用的BootstrapVue组件本身也有一定的渲染开销,全量重渲染时叠加的计算量超过了浏览器每帧16ms的预算,就会出现输入卡顿
解决方案
可以按照优先级选择以下优化方案:
- 组件拆分(最优先)
把列表部分单独封装成独立子组件,仅将appKeys作为props传入子组件。父组件修改form对象时,子组件的props没有发生变化,就不会触发子组件的重渲染,从根源上避免不必要的计算。 - 使用v-memo指令控制渲染粒度
如果你用的是Vue3,可以给b-list-group-item加上v-memo="[key]"属性,只有当对应的key对象发生变化时才会重渲染这一个条目,既保留了新增/修改/删除条目时的响应性,又避免了无关更新触发的全量列表重渲染,比v-once更灵活。
如果是Vue2环境,可以引入第三方的vue-memo指令实现相同效果。 - 提前格式化数据,移除模板内计算逻辑
不要在模板中使用过滤器或者表达式做格式化计算,调用接口拿到appKeys数据时就提前把expired、created字段格式化成要展示的字符串,存到每个条目的属性里,渲染时直接读取已经格式化好的属性即可,避免每次重渲染都重复执行格式化逻辑。 - 虚拟滚动(扩展优化)
如果后续列表条目会增长到上千条,可以引入虚拟滚动组件,只渲染可视区域内的条目,进一步降低渲染开销。
内容的提问来源于stack exchange,提问作者Rey
相关产品推荐
相关产品推荐

