代码层面的优化
组件拆分: 将大型组件拆分为小的、可复用的子组件,遵循单一职责原则,使得每个组件只关注特定的功能。这样可以提高代码的可读性、可维护性,并使得组件复用更容易
异步组件: 对于一些页面或组件,使用 Vue 的异步组件和路由懒加载技术。这样可以将页面加载时间分散到多个小模块上,避免一次性加载过多的组件,提高页面加载速度。
// 全局注册时按需加载
Vue.component(
'async-webpack-example',
// 这个动态导入会返回一个 `Promise` 对象。
() => import('./my-async-component')
)
// 局部注册按需加载
components: {
'my-component': () => import('./my-async-component')
}
// 路由应用时按需加载
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [{ path: '/foo', component: Foo }]
})
//动态组件按需加载 currentTabComponent 组件name或组件对象
<component v-bind:is="currentTabComponent"></component>
数据缓存: 对于一些不经常变化的数据,可以在组件中使用 computed 属性或 vuex 中的 getters 来进行数据缓存,避免重复计算和请求。(computed使用优先级要高于方法)
事件代理:
<ul @click="onClick">
<li v-for="item in list" :key="item.name" :data-id="item.id">{{ item.name }}</li>
</ul>
export default {
methods: {
onClick(e) {
console.log("e.target", e.target, e.target.dataset.id);
},
},
};
v-for 的 key: 当使用 v-for 循环渲染列表时,确保为每个项提供唯一的 key 属性,这样 Vue 可以更高效地跟踪列表项的变化。
v-if 和 v-show: v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
避免不必要的响应式: 对于不需要响应式的数据,使用 Object.freeze 或直接设置为普通对象,避免 Vue 进行不必要的响应式处理。对于纯展示的大数据,都可以使用Object.freeze提升性能。
<template>
<div class="">
<ul>
<li v-for="item in list" :key="item.name" :data-id="item.id">{{ item.name }}</li>
</ul>
<button @click="onEdit">edit list</button>
</div>
</template>
<script>
export default {
name: "App",
components: {},
props: {},
data() {
return {
list: Object.freeze([
{ name: "bwf", age: 20, id: "11" },
{ name: "xx", age: 90, id: "22" },
{ name: "li", age: 30, id: "33" },
]),
users: {}
};
},
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
},
methods: {
onEdit() {
// 会冻结改变 视图不会渲染,但是list对象的值是改变了
this.list[0].name = "wmy";
// 当更改这个对象的地址后,则不会被冻结,以下改变可以引起页面的响应式
this.list = [{ name: "xx", age: 90, id: "22" }];
},
},
};
</script>
使用 keep-alive: 对于需要频繁切换的组件,可以使用 <keep-alive> 来缓存组件状态,避免重复渲染。
v-for和v-if不要同时使用,因为vue2中v-for优先级高于v-if 也就是说,如果在同一个元素上同时使用了 v-for 和 v-if,v-for 会先执行,然后再执行 v-if,这样会导致在每次渲染时都执行,而不是在符合条件时才执行;避免同时使用 v-for 和 v-if 可以通过computed来处理:
<template>
<div>
<div v-for="item in filteredItems" :key="item.id">{{ item.name }}</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ id: 1, name: 'Item 1', condition: true },
{ id: 2, name: 'Item 2', condition: false },
// ...
],
};
},
computed: {
filteredItems() {
return this.items.filter(item => item.condition);
}
}
};
</script>
事件定时器等副作用的及时销户
第三方插件的按需引入
import Vue from 'vue';
import { Button, Select } from 'element-ui';
Vue.use(Button)
Vue.use(Select)
服务端渲染:服务端渲染是指 Vue 在客户端将标签渲染成的整个 html 片段的工作在服务端完成,服务端形成的 html 片段直接返回给客户端这个过程就叫做服务端渲染
- 更好的 SEO,因为 SPA 页面的内容是通过 Ajax 获取,而搜索引擎爬取工具并不会等待 Ajax 异步完成后再抓取页面内容
- 更快的内容到达时间(首屏加载更快)
打包方面和网络方面的优化
使用生产环境构建: 在部署 Vue 项目时,确保使用生产环境构建,即通过命令行参数或配置文件指定打包模式为生产模式。这会自动进行代码压缩和优化,减小文件体积,提高加载速度。
Tree Shaking: 确保启用 Tree Shaking 特性,它可以在打包过程中去除未使用的代码,减少最终的输出文件大小。使用 ES6 模块和静态引入可以更好地支持 Tree Shaking。
使用 CDN 加载资源: 对于一些公共的库或框架,可以考虑使用 CDN 加载,这样可以利用浏览器缓存,并且不需要将这些资源打包进应用程序的代码中。
gzip/br 压缩: 在服务器端启用 gzip/br 压缩,可以进一步减小传输的文件大小,提高页面加载速度。HTTP 响应的 Content-Encoding 头部,相比 gzip,Brotli 压缩算法具有更高的压缩率,能够产生更小的文件大小,但并不是所有的浏览器和服务器都支持
缓存策略: 使用适当的缓存策略,例如配置 HTTP 缓存头,利用浏览器缓存,以减少重复请求和数据传输。