当前位置: 首页 > news >正文

Vue常用优化

使用key

帮助 Vue 高效更新虚拟 DOM

<!-- 推荐:使用唯一ID -->
<div v-for="item in items" :key="item.id"><!-- 避免:使用索引作为key(除非列表简单且无状态) -->
<div v-for="(item, index) in items" :key="index">
使用冻结对象

冻结对象不会被响应化

// 对于纯展示的大数据对象
this.largeData = Object.freeze(bigData);// 冻结数组避免意外修改
this.staticList = Object.freeze([...]);
使用函数式组件

https://cn.vuejs.org/guide/extras/render-function.html#functional-components

减少javaScript执行时间,渲染时间,内存占用大小

没有在像其他组件内部new VueComponent 创建Vue组件实例,只做纯渲染

适用场景:纯展示组件,无状态、无实例、无生命周期

export default {functional: true,props: ['value'],render(h, { props }) {return h('div', props.value)}
}
使用计算属性

如果模板中某个数据会使用多次,并且该数据是通过计算得到的,使用计算属性以缓存它们

computed: {filteredItems() {return this.items.filter(item => item.active);}
}
非实时绑定的表单项

对于表单输入,默认的v-model会监听@input事件,每当输入框的值发生变化时立即触发,导致每次输入都触发数据更新和视图重渲染。可以通过以下方式优化:

  • 使用v-model.lazy:监听change事件,当输入框失去焦点且值发生变化时触发,减少更新频率。

    <input v-model.lazy="searchQuery" />  
    
  • 手动绑定值和事件:完全控制数据更新时机。

    <input :value="searchQuery" @change="updateQuery($event.target.value)" />
    

注意:这可能导致数据与表单控件暂时不同步,需根据具体需求权衡使用。

<!-- 减少输入时的频繁更新 -->
<input v-model.lazy="searchQuery"><!-- 手动实现(更灵活控制) -->
<input :value="searchQuery" @change="updateSearch">
保持对象引用稳定

在绝大部分情况下,vue 触发 rerender 的时机是其依赖的数据发生变化

若数据没有发生变化,哪怕给数据重新赋值了,vue也是不会做出任何处理

// 不推荐:会导致引用变化
this.obj = { ...this.obj, value: newValue };// 推荐:保持引用不变
this.obj.value = newValue;
this.$set(this.obj, 'value', newValue);

下面是vue判断数据没有变化的源码

function hasChanged(x, y){if (x === y){return x === 0 && 1 / x !== 1 / y} else {return x === x || y === y}
}

因此,如果需要,只要能保证组件的依赖数据不发生变化,组件就不会重新渲染。

  • 原始类型:直接赋值即可。
  • 对象类型:避免直接修改原对象,使用合并或替换策略。
使用v-show替代v-if

对于频繁切换显示状态的元素,使用v-show可以保证虚拟dom树的稳定,避免频繁的新增和删除元素,特别是对于那些内部包含大量dom元素的节点,这一点极其重要

<!-- 适合频繁切换的场景 -->
<HeavyComponent v-show="active" /><!-- 适合运行时条件很少改变的场景 -->
<HeavyComponent v-if="shouldRender" />
使用延迟装载(defer)

JS传输完成后,浏览器开始执行JS构造页面。

但可能一开始要渲染的组件太多,不仅JS执行的时间很长,而且执行完后浏览器要渲染的元素过多,从而导致页面白屏

可以通过延迟装载组件,让组件按照指定的先后顺序依次一个一个渲染出来

延迟装载是一个思路,本质上就是利用 requestAnimationFrame 事件分批渲染内容,它的具体实现多种多样

methods: {deferRender() {requestAnimationFrame(() => {this.showComponent = true;});},
},
mounted() {this.deferRender();
},
function renderBatch(components) {requestAnimationFrame(() => {components.forEach(component => component.render());});
}
使用keep-alike

对于频繁切换的动态组件,使用<keep-alive>可以缓存组件状态,减少重新渲染和数据获取的开销。

  • 配合 include/exclude 精确控制
<keep-alive :include="['ComponentA', 'ComponentB']"><component :is="currentComponent"></component>
</keep-alive>

注意事项:

  • 适用于需要保留状态的组件,如表单、数据列表等。
  • 对于不需要缓存的组件,可以使用exclude属性或动态条件控制。
长列表优化

处理大量数据渲染时,常规的v-for可能导致性能问题

  • 虚拟滚动:对于超长列表,只渲染可视区域内的少量元素,其他部分使用占位符

    • 第三方库:如vue-virtual-scroller
    • 自定义实现:监听滚动事件,动态计算并渲染可见元素。
  • 分页/懒加载:按需加载和渲染

  • 冻结非可视区域数据

    // 只响应化当前可视区域的数据
    this.visibleItems = Object.freeze(items.slice(start, end));
    
图片懒加载

使用 IntersectionObserver 或第三方库(如 vue-lazyload)实现图片懒加载。

<img v-lazy="imageSrc" alt="Lazy Loaded Image">
SSR(服务端渲染)

提升首屏加载速度,改善 SEO。

  • 使用 Nuxt.js 或 Vue SSR 提供的服务端渲染能力。
  • 配合 CDN 缓存静态页面。
自定义指令优化

复杂 DOM 操作使用自定义指令

打包优化
  • 路由懒加载

    const Data = () => import(/* webpackChunkName: "Data" */ './Data.vue')
    
  • 按需引入

    // 例如ElementUI
    import { Button, Select } from 'element-ui';
    
  • Tree-shaking

    移除未使用的代码

    • ES6模块语法:使用importexport,便于打包工具分析依赖。

    • 避免副作用导入:确保只导入需要的模块部分。

  • 压缩

    代码压缩、静态资源压缩(图片压缩工具imagemin等)

    启用Terser插件,压缩JavaScript代码,减小体积

    // vue.config.js
    module.exports = {productionSourceMap: false,configureWebpack: {optimization: {minimize: true}}
    }
    
  • 使用轻量级替代方案:例如,使用lodash-es代替完整的lodash,减少包大小。

  • 分析工具

    vue-cli-service build --report
    

相关文章:

  • jeecg查询指定时间
  • 系统架构设计师:设计模式——行为设计模式
  • 【Touching China】2007-2011
  • WordPress不支持中文TAG标签出现404的解决方法
  • ES6入门---第三单元 模块三:async、await
  • LeetCode每日一题5.4
  • C++多态(上)
  • Java面试大纲(以及常见面试问答)
  • 如何查看电脑IP地址和归属地:全面指南
  • 强化学习机器人模拟器——RobotApp:一个交互式强化学习模拟器
  • Dify框架面试内容整理-Dify部署后常见问题有哪些?如何排查?
  • 【循环依赖(Circular Dependency)】
  • C++多态(下)
  • 自监督学习(Self-supervised Learning)李宏毅
  • 第十章.XML
  • langchain中 callbacks constructor实现
  • devtmpfs_create_node
  • WPF中Binding
  • 判断声音“混”的原因
  • 委托构造函数是什么?
  • 中国戏剧梅花奖终评结果公示,蓝天和朱洁静等15名演员入选
  • 上海银行副行长汪明履新上海农商银行党委副书记
  • 调查:“网约摩的”上线起步价五六元,合规性及安全性引质疑
  • 15年全免费,内蒙古准格尔旗实现幼儿园到高中0学费
  • 浙江美术馆馆长人民日报撰文:打开更辽阔的审美场域
  • 英国警方再逮捕一名涉嫌参与首相住宅纵火案嫌疑人