eslint-plugin-vue icon indicating copy to clipboard operation
eslint-plugin-vue copied to clipboard

rule: no v-if on template root

Open privatenumber opened this issue 3 years ago • 2 comments

Please describe what the rule should do:

Warn on using v-if on the template root node, because:

  1. Whether a component should be rendered or not is a usage concern. Specifically, it's confusing when a declared component is not rendered:

    /* Usage */
    <template>
        <div>
            ...
            <custom-component /> /* Readers expect this to be rendered */
        </div>
    </template>
    
    
    /* CustomComponent.vue */
    <template>
        <div v-if="false">
            ...
        </div>
    </template>
    
  2. There are performance benefits:

    1. Instantiating a new stateful component only for it to not be rendered via root v-if="false" is wasteful. If possible, it should happen in the parent usage life-cycle.
    2. When moving the v-if to the parent, the component can be asynchronously loaded when needed, so not only will it save on component registration, it will save on module declaration and asset size.
      <template>
          <div>
              ...
              <custom-component v-if="shouldShow" /> /* Won't be loaded till true */
          </div>
      </template>
      
      <script>
      export default {
      	components: {
              CustomComponent: () => import('./CustomComponent.vue')
          }
      }
      </script>
      

What category should the rule belong to?

[ ] Enforces code style (layout) [ ] Warns about a potential error (problem) [x] Suggests an alternate way of doing something (suggestion) [ ] Other (please specify:)

Provide 2-3 code examples that this rule should warn about:

Bad

/* Usage */
<template>
    <div>
        <custom-component />
    </div>
</template>


/* CustomComponent.vue */
<template>
    <div v-if="shouldShow">
        ...
    </div>
</template>

Good

/* Usage */
<template>
    <div>
        <custom-component v-if="shouldShow" />
    </div>
</template>


/* CustomComponent.vue */
<template>
    <div>
        ...
    </div>
</template>

Additional context

  • There are likely cases where it's not possible to do this. I think this would be a warning in "recommended", or not even a pre-enabled rule.

privatenumber avatar Mar 26 '21 21:03 privatenumber

Thank you for rule proposal! I think it's good to make it rule available to users.

I think the following template needs to be valid.

<template>
    <div v-if="mode === 'a'">
        ...
    </div>
    <div v-if="mode === 'b'">
        ...
    </div>
</template>
<template>
    <div v-if="loading">
        ...
    </div>
    <div v-else>
        ...
    </div>
</template>

ota-meshi avatar Apr 01 '21 08:04 ota-meshi

Yeah that's a great point. Good catch!

privatenumber avatar Apr 01 '21 19:04 privatenumber

I think that this is already covered by this rule vue/valid-template-root

chelorope avatar Dec 23 '22 19:12 chelorope

How so?

privatenumber avatar Dec 24 '22 03:12 privatenumber

I would like to work on this @ota-meshi

songpengyuan avatar Mar 24 '23 03:03 songpengyuan

Yeah, thank you!

ota-meshi avatar Mar 24 '23 04:03 ota-meshi