这在用于大型数据结构时性能消耗较大,仅在必要时使用。
export default {
watch: {
someObject: {
handler(newValue, oldValue) {
},
deep: true
}
}
}
尤其是配合动态组件时使用,使常用组件进行缓存,减少组件创建与卸载,提高响应速度与资源利用率。
<KeepAlive :include="/a|b/">
<component :is="view" />
KeepAlive>
对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
解决数据多级传递问题,如果数据仅在多层嵌套的父子级组件中使用,那么就不用麻烦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中的数据越少越好。
将可重用的功能处理逻辑使用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>
向子组件传值时仅传递必要的值,减小数据传递的代价,也避免了不必要的更新。
<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>
<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渲染速度会更快,但其都有自己的缺点,要结合实际情况进行取舍使用。
使用v-for时,要考虑如何编写语法才能最小化列表更新代价。
<ListItem
v-for="item in list"
:id="item.id"
:active-id="activeId" />
<ListItem
v-for="item in list"
:id="item.id"
:active="item.id === activeId" />
且对于经常变动的列表,要善于使用key
来对每一个元素进行标记,这有利于diff算法的比较。
将使用了响应式数据但无需更新的元素添加v-once标签来避免不必要的DOM更新渲染。
<span v-once>This will never change: {{msg}}span>
<div v-once>
<h1>commenth1>
<p>{{msg}}p>
div>
<my-component v-once :comment="msg">my-component>
<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节点昂贵的多。