Single File Component with slot gets unexpectedly re-rendered on parent event

273 views Asked by At

I am not very confortable with Vue slots yet so maybe I'm using them wrongly. I have 2 Single File Components that are defined the following way :

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>

What I don't understand is : when the mouseover event in the HelloWorld SFC is triggered, the beforeUpdate method of Info.vue is called 3 times each time (as many times as there are items in my list). How come this method is called (since no data passed to the Info component is changed) and how can I prevent this potentially costly re-render? Interestingly, the re-render doesn't happen if I remove the class attribute in HelloWorld that toggles the line highlight.

The full code is here : https://codesandbox.io/s/tender-swanson-57oev

1

There are 1 answers

1
nishkaush On

This is happening because highlighted class has to be evaluated for each element, every time mouseover event takes place.

This happens because highlighted prop changes every time mouseover takes place, which re-triggers Vue to figure out which element to attach the highlighted css class to.