内容提要
本文介绍Vue项目优化技巧:拆分组件以缩小更新粒度,避免大表格中弹窗输入卡顿;用轻量自研组件替代重型开源库;用v-if和异步组件加快首屏;分块渲染提升滚动流畅度;缓存AJAX数据;用Object.freeze冻结只读数据;循环加key加速diff。
延伸解读
组件拆分:从抽象到性能优化
文章指出,拆分组件不仅是代码抽象的手段,更是提升性能的有效方式。在大型表格中,弹窗输入卡顿的根源在于单个组件内数据变更会触发整个组件的重新渲染和diff。将弹窗拆分为独立子组件后,其内部更新不会影响父组件,父组件更新时也不会重新渲染无数据变化的子组件,从而实现双向优化。但需注意,若组件使用了插槽,子组件仍会随父组件重新渲染。
轻量自研组件:应对重型库的冗余
开源库虽好,但为满足通用性往往包含大量冗余逻辑。当业务中需要循环渲染数十甚至上百个表格时,这些冗余逻辑会显著影响效率并增加内存消耗。文章建议,在必要时可自研最简组件,仅满足最小需求,例如作者自建的表格组件和轻量校验插件。实现时可能需要熟悉render函数,以便更自由地操作节点结构。
首屏加速:v-if与异步组件的配合
若追求极致的首屏渲染速度,v-if是有效工具,它能避免初始渲染不必要的组件。结合异步组件和webpack的代码分割,可以延迟加载部分代码或大型JavaScript文件,进一步优化首屏。另一方面,v-show适合需要频繁切换的场景,因为它能缓存组件,提升切换流畅度。两者需根据实际使用频率权衡选择。
数据与渲染优化:缓存、冻结与分块
文章提供了多项数据与渲染优化技巧:缓存AJAX数据可避免重复请求,通过封装axios并在sessionStorage中存储响应实现;使用Object.freeze冻结只读数据(如表格数据),能跳过递归的响应式转换,对大型深层对象节省显著;分块渲染可提升滚动流畅度,避免长任务阻塞渲染;循环时使用唯一key加速diff,但切忌用index作为key,否则可能导致无限重渲染。
Q&A
Vue 项目中,为什么把弹窗拆成独立组件能提升性能?
因为 Vue 的更新是以组件为单位的。在单个组件内修改数据会触发整个组件的 render 和 diff,而将弹窗拆成子组件后,子组件内部的更新不会触发父组件更新,父组件更新时也不会重新渲染没有数据变化的子组件,从而减少不必要的渲染,提升性能。
Vue 项目首屏加载慢,有哪些优化方法?
可以使用 v-if 控制初始渲染,并结合异步组件(如 () => import('./my-async-component'))延迟加载部分代码;利用 webpack 的代码分割功能延迟加载大型 JavaScript 文件;另外,使用 v-show 可以缓存组件,提高切换流畅度。
如何优化 Vue 中大型表格的滚动流畅度?
可以采用分块渲染(chunk rendering)来提升滚动流畅度。因为浏览器渲染和 JavaScript 执行是互斥的,如果一段代码执行时间超过 1000/30 毫秒,就会导致帧率低于 30 帧。通过分块渲染可以避免长时间阻塞渲染。
Vue 中如何缓存 AJAX 请求数据?
可以封装一个带缓存的 ajax 对象,在发起 GET 请求前,根据 URL 和参数生成唯一 id,检查 sessionStorage 中是否已有缓存,如果有则直接返回缓存的 Promise,否则发起请求并在响应拦截器中将数据存入 sessionStorage。
Object.freeze 在 Vue 中有什么优化作用?
对于只读数据(如表格数据),使用 Object.freeze() 可以阻止 Vue 将其转换为响应式数据,从而节省递归设置响应式所花费的时间。对于大型深层对象,节省的时间相当显著。
Vue 循环中 key 的作用是什么?为什么不能用 index 作为 key?
key 的作用是加速 diff 算法。但不要使用简单的 index 作为 key,因为当列表顺序变化时,index 会导致错误的复用,可能引发不必要的重新渲染甚至无限循环。每个子元素应该使用不同的、稳定的 key。