带有插槽的单个文件组件在父事件中意外地重新呈现

问题描述

我对Vue插槽并不十分满意,所以也许我错误地使用了它们。我有2个单一文件组件,它们通过以下方式定义:

HelloWorld.vue:

<template>
  <div>
    <div
      v-for="item in items"
      :key="item"
      @mouSEOver="highlighted = item"
      :class="{ highlighted: highlighted === item }"
    >
      {{ item }}
      <Info>
        <img
          src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png"
        />
      </Info>
    </div>
  </div>
</template>
<script>
import Info from "./Info.vue";

export default {
  name: "HelloWorld",components: {
    Info,},data: () => ({
    highlighted: null,items: [1,2,3],}),};
</script>
<style scoped>
.highlighted {
  background: grey;
}
</style>

Info.vue:

<template>
  <div><slot /></div>
</template>

<script>
export default {
  name: "Info",beforeUpdate() {
    console.log("beforeUpdate Info.vue");
  },};
</script>

我不了解的是:触发mouSEOver SFC中的HelloWorld事件时,beforeUpdate的{​​{1}}方法每次被调用3次(次数是我列表中的所有项目)。如何调用方法(由于没有更改传递到Info.vue组件的数据),如何防止这种可能代价高昂的重新渲染?有趣的是,如果我删除Info中的class属性来切换行高亮,则不会发生重新渲染。

完整代码在这里https://codesandbox.io/s/tender-swanson-57oev

解决方法

之所以会这样,是因为每次发生鼠标悬停事件时,都必须为每个元素评估highlighted类。

之所以发生这种情况,是因为highlighted道具每次鼠标悬停都会发生变化,这会重新触发Vue以确定将highlighted css类附加到哪个元素。