[vue面试题]4、key的作用

1、测试环境准备

<template>
    <div>
        <div ref="container">
            <div v-for="item, index in dataList" :key="item.name">{{ item.name }}
                <div style="margin-left: 10px;">{{ item.child }}</div>
            </div>
        </div>
        <button @click="add">增加</button>
        <button @click="insert">插入</button>
    </div>
</template>

<script lang="ts" setup>
import { ref, onMounted } from 'vue';

const dataList = ref([{ name: 1, child: "1-1" }, { name: 2, child: "1-2" }]);
const add = () => {
    const num = Math.random() * 100;
    const child_num = `${num}_${Math.random() * 200}`;
    dataList.value.push({ name: num, child: child_num });
}

const insert = () => {
    const num = Math.random() * 100;
    const child_num = `${num}_${Math.random() * 200}`;
    dataList.value.splice(1, 0, { name: num, child: child_num });
}

const container = ref(null);

onMounted(() => {
    // 创建一个 MutationObserver 实例,并指定回调函数
    const observer = new MutationObserver((mutationRecords) => {
        for (const record of mutationRecords) {
            // 检查变动类型
            if (record.type === 'childList') {
                if (record.addedNodes.length > 0) {
                    for (const addedNode of record.addedNodes) {
                        console.log('新增的节点:', addedNode);
                    }
                }
                if (record.removedNodes.length > 0) {
                    for (const removedNode of record.removedNodes) {
                        console.log('移除的节点:', removedNode);
                    }
                }
            } else if (record.type === 'attributes') {
                console.log('属性变化:', record.target, '属性名称:', record.attributeName);
            } else if (record.type === 'characterData') {
                console.log('文本内容变化:', record.target);
            }
        }
    });

    // 开始观察指定的 DOM 节点及其子节点的变动
    observer.observe(container.value, {
        childList: true,      // 监听子节点的添加和删除
        attributes: true,     // 监听属性变化
        characterData: true,  // 监听文本内容变化
        subtree: true         // 监听整个子树
    });
});
</script>

<style lang="scss" scoped></style>

mutationObserver:提供了监视对 DOM 树所做更改的能力

有了这个测试环境,所有对dom的更改我们都可以一目了然

2、key为唯一值的情况

当key为一个唯一值的情况下,这也是vue推荐的做法:

我们可以看到仅新增了5.812019637998778一个节点,其他节点并没有移动、删除的操作,这是因为vue会根据key进行最大可能的dom复用。

3、key没有设置的情况下

可以看出,vue对元素进行了“就地复用”,也就是仅仅按照顺序将内容进行了覆盖,原来“2”这个文本被覆盖为了90_141,“1-2”子节点会被删除,然后新增“90_141”子节点,然后重新创建了2号节点和1-2子节点,这对于长列表和深层结构的组件显然是会浪费巨量的渲染时间,所以我们应该尽量设置唯一的key值辅助vue进行渲染操作。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部