vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.61k stars 8.32k forks source link

Using v-if with v-slot directive cause unnecessary update hook #6833

Open nndnha opened 2 years ago

nndnha commented 2 years ago

Vue version

3.2.40

Link to minimal reproduction

https://sfc.vuejs.org/#eNqNU81u2zAMfhVWOyRBYynddsocp8Mu6wMMu+jixkzs1vqBJDsoDL97KTtNnRYtejEo/nwkP37u2G9redsgW7PU71xlA3gMjc2krpQ1LkAHDvdLMPqfLfKABfSwd0bBjKpm56w/RtnRLxkX8RVRJZNa6p3RPsDONDqgg03Em68WMXIGnc8XsMmgkxooUXtTI6/NYT6j8V5bz6ioX/yKlTTkXYRr8/qydmjCyd3g9TWl9sub1Sp2S8W4H21Gj4DK1oRJL4C0vMm67jxh36eCPEMkbjJYZL/UQJtU+41kwcUN4VuJeYEug/QqSeBuD0ekFZVpx0QIJer4AevMfY0KjlVdw8FAfsyfIElO8AB/Bxwo0eGpo7gcc+CVzImfLdl4gUTllj94o+mSAxXyFPCSrUdyom84ypqMMgTr10I02j4e+M4ocUsx4YiCSmFSGHX7g3/nP1eiqHyY+jl6ldw7c/RE9APBLyfggpwtusShpl3QfdrsTe5Fwzexd01jz57OSwS8qC1qeEJY6msTQOcK6VbjjSTLSAbkviQx5n6g/Y9k/xXtDv/EOe0K/pdP2+12FPFEj6x/BvZ7Mxs=

Steps to reproduce

Open the devtools to see the log messages.

What is expected?

onUpdated shouldn't be called on Comp component.

What is actually happening?

onUpdated is called on both App and Comp.

System Info

No response

Any additional comments?

No response

liulinboyi commented 2 years ago

Because it's DYNAMIC_SLOTS, the function shouldUpdateComponent will return true, the component will update and the lifecycle onUpdated will trigger. https://github.com/vuejs/core/blob/2a9e9a40963a852238adc4c61b86d0c48e7131fa/packages/runtime-core/src/componentRenderUtils.ts#L345-L349 image

nndnha commented 2 years ago

@SuzumiyaHaku v-if="true" doesn't make sense in any real apps, I used it just to make a short description of the problem and the real problem is something like this

SuzumiyaHaku commented 2 years ago

I think you need the v-memo directive.

<template>
  <h1>{{ counter }}</h1>
  <Comp  v-memo="[showHeader]">
    <template v-if="showHeader" #header>
      Header here
    </template>
  </Comp>
</template>
nndnha commented 2 years ago

@SuzumiyaHaku Thanks for your v-memo suggestion! There is another way to solve this:

<template>
  <h1>{{ counter }}</h1>
  <Comp>
    <template #header>
      <template v-if="showHeader">
         Header here
      </template> 
    </template>
  </Comp>
</template>

The main point of this issue is that I think the combination of v-if and v-slot in this case surely is a performance pitfall so we either fix it, or we should at least mention it to the docs.