Vue性能优化方案——个人经验总结
Vue性能优化方案——个人经验总结谨慎使用深度监听善于使用\props与emit验证减小项目体积provide和inject善用异步加载“慎用”Vuex功能重用仅传递必要的数据设计模块分类SSR/SSGv-for优化善用v-once列表虚拟化非反应性减少组件谨慎使用深度监听这在用于大型数据结构时性能消耗较大,仅在必要时使用。export default {watch: {someObject: {
Vue性能优化方案——个人经验总结
谨慎使用深度监听
这在用于大型数据结构时性能消耗较大,仅在必要时使用。
export default {
watch: {
someObject: {
handler(newValue, oldValue) {
},
deep: true
}
}
}
善于使用 KeepAlive
尤其是配合动态组件时使用,使常用组件进行缓存,减少组件创建与卸载,提高响应速度与资源利用率。
<KeepAlive :include="/a|b/"> <!-- 表示仅缓存name为a或b的组件 -->
<component :is="view" />
</KeepAlive>
props与emit验证
对props和emits进行必要的验证,提高数据准确性,减小组件因为数据而出错。
export default {
props: {
// Basic type check
// (`null` and `undefined` values will allow any type)
propA: Number,
// Multiple possible types
propB: [String, Number],
// Required string
propC: {
type: String,
required: true
},
// Number with a default value
propD: {
type: Number,
default: 100
},
// Object with a default value
propE: {
type: Object,
// Object or array defaults must be returned from
// a factory function. The function receives the raw
// props received by the component as the argument.
default(rawProps) {
// default function receives the raw props object as argument
return { message: 'hello' }
}
},
// Custom validator function
propF: {
validator(value) {
// The value must match one of these strings
return ['success', 'warning', 'danger'].includes(value)
}
},
// Function with a default value
propG: {
type: Function,
// Unlike object or array default, this is not a factory function - this is a function to serve as a default value
default() {
return 'Default function'
}
}
}
}
减小项目体积
使用Componsition API开发,将vue的方法按需引入,以免在打包时将未用到的API打包进去。
import { ref, onMounted, onUnmounted } from 'vue'
provide和inject
使用provide
和inject
解决数据多级传递问题,如果数据仅在多层嵌套的父子级组件中使用,那么就不用麻烦Vuex。
// 在上级组件中使用provide将数据传下去
export default {
data() {
return {
message: 'hello!'
}
},
provide() {
// use function syntax so that we can access `this`
return {
message: this.message
}
}
}
// 在下级组件中使用inject接收数据
export default {
inject: ['message'], // 可以使用别名,定义默认值
data() {
return {
fullMessage: this.message
}
}
}
善用异步加载
使用defineAsyncComponent
异步加载仅在需要时才会加载的组件。可配合router使用,提高首屏渲染速度。
import { defineAsyncComponent } from 'vue'
export default {
// ...
components: {
AsyncComponent: defineAsyncComponent(() =>
import('./components/AsyncComponent.vue')
)
}
}
“慎用”Vuex
不要为了使用Vuex而使用Vuex,能在组件内解决的问题就不要麻烦Vuex。Vuex中的数据需要绑定更多的依赖,所以Vuex中的数据越少越好。
功能重用
将可重用的功能处理逻辑使用Componsition API的形式单独封装起来,然后按需使用。
比如鼠标位置显示功能:
// 功能封装 mouse.js
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
return { x, y }
}
// 使用
<script setup>
import { useMouse } from './mouse.js'
const { x, y } = useMouse()
</script>
<template>Mouse position is at: {{ x }}, {{ y }}</template>
仅传递必要的数据
向子组件传值时仅传递必要的值,减小数据传递的代价,也避免了不必要的更新。
<!-- bad -->
<template>
<myComponent :msgObj="msgObj" />
</template>
<script>
import { reactive } from 'vue'
export default {
components: { myComponent },
setup() {
const mstObj = reactive({
name: 'wei',
age: '22',
data: '2022.05.08',
// ...
})
return {
msgObj
}
}
};
</script>
<!-- good -->
<template>
<myComponent
:name="msgObj.name"
:age="msgObj.age"
/>
</template>
<script>
import { reactive } from 'vue'
export default {
components: { myComponent },
setup() {
const mstObj = reactive({
name: 'wei',
age: '22',
data: '2022.05.08',
// ...
})
return {
msgObj
}
}
};
</script>
设计模块分类
在设计之初就将模块进行分类,实时渲染、延迟渲染、缓存机制等分类,有利于推断系统的运行过程,且后续开发时每个组件也有自己的定位,知道自己应该什么时候渲染,是否有直接渲染的优先级。
SSR/SSG
SSR/SSG渲染速度会更快,但其都有自己的缺点,要结合实际情况进行取舍使用。
v-for优化
使用v-for时,要考虑如何编写语法才能最小化列表更新代价。
<!-- bad -->
<ListItem
v-for="item in list"
:id="item.id"
:active-id="activeId" />
<!-- good -->
<ListItem
v-for="item in list"
:id="item.id"
:active="item.id === activeId" />
且对于经常变动的列表,要善于使用key
来对每一个元素进行标记,这有利于diff算法的比较。
善用v-once
将使用了响应式数据但无需更新的元素添加v-once标签来避免不必要的DOM更新渲染。
<!-- single element -->
<span v-once>This will never change: {{msg}}</span>
<!-- the element have children -->
<div v-once>
<h1>comment</h1>
<p>{{msg}}</p>
</div>
<!-- component -->
<my-component v-once :comment="msg"></my-component>
<!-- `v-for` directive -->
<ul>
<li v-for="i in list" v-once>{{i}}</li>
</ul>
列表虚拟化
使用列表虚拟化的方法来渲染大型列表:vue-virtual-scroller、vue-virtual-scroll-grid。
非反应性
减少大型不可变结构的反应性开销,灵活运用shallowRef()
和shallowReactive()
来创建浅反应式数据。
const state = shallowRef({ count: 1 })
// does NOT trigger change
state.value.count = 2
// does trigger change
state.value = { count: 2 }
减少组件
避免不必要的组件抽象,因为组件实例比DOM节点昂贵的多。
避免内存泄漏
- 避免意外的全局变量
- 避免使用不当的闭包
- 及时清除定时器与不用的数据,一般会在unMounted中执行
更多推荐
所有评论(0)