core icon indicating copy to clipboard operation
core copied to clipboard

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

Open nndnha opened this issue 1 year ago • 4 comments

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

nndnha avatar Oct 07 '22 15:10 nndnha

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

liulinboyi avatar Oct 07 '22 18:10 liulinboyi

@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

nndnha avatar Oct 13 '22 11:10 nndnha

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>

SuzumiyaHaku avatar Oct 14 '22 10:10 SuzumiyaHaku

@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.

nndnha avatar Oct 14 '22 10:10 nndnha