Vue 3.2版本新增了v-memo指令,memo从字面意思理解是备忘录。它可以接受一个数组,数组中存放依赖的值,数组中的依赖值都没有发生变化时,使用v-memo的组件/元素将跳过组件更新(包括其子树)。
比如:
<template>
<div v-memo="[name]">
<div>{{ name }}</div>
<div>{{ age }}</div>
<div>{{ message }}</div>
</div>
<button @click="handleBtnClick">change</button>
</template>
<script setup>
import { ref } from 'vue';
const name = ref('loftyamb')
const age = ref(24)
const handleBtnClick = () => {
age.value++ // age值的变化将不会更新到页面中,除非name发生变化
}
v-memo能够在一些场景下对性能进行细小的优化(不该被滥用),例如:
假设我们有一个长列表需要渲染,并且列表项会因为用户的操作发生变化:
<template>
<div class="memo-demo">
<ul>
<li
v-for=" item in 5"
:key="item"
:class="{ active: item === active }"
@click="handleItemClick(item)"
:ref="handleRefChange">
{{ item }}
</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue'
const handleRefChange = () => {
console.log('change');
}
const active = ref(1);
const handleItemClick = (item) => {
active.value = item;
};
</script>
<style scoped>
.active {
color: red;
}
</style>
上面代码中的handleRefChange
会在每次绑定ref的元素更新时(包括初始化)被调用,我们可以在浏览器控制台中看到li元素初始化的时候被调用5次(因为遍历生成了5个li元素):
而如果我们点击其中一个非active的li元素时,我们会发现handleRefChange
又再次被调用了5次,也就是5个li元素都发生了更新(因为它们所依赖的active
值变化了):
但实际上,我们并不需要对每个li元素都进行更新,只需要对所依赖item === active
的值发生更新的时候才进行更新即可。在这种情况下,我们可以使用v-memo
指令来实现优化:
<li
v-for=" item in 5"
:key="item"
:class="{ active: item === active }"
@click="handleItemClick(item)"
v-memo="[item === active]"
:ref="handleRefChange">
{{ item }}
</li>
当使用了v-meomo
指令之后,我们就会发现每次点击非active的li元素的之后,handleRefChange
只被调用2次,因为只有点击之前「active的li元素」和「被点击的li元素」所依赖的item === active
值会发现变化:
通过v-memo
指令,我们可以在更新内容很多时减少一些不必要的更新,从而对性能进行优化。