Subscribe on changes!

Vue3 warns even if v-bind="$attrs" and inheritAttrs: false are present on multi-root component

avatar
Oct 6th 2022

Vue version

v3.2.40

Link to minimal reproduction

https://sfc.vuejs.org/#eNp9Ue1OwzAMfBUrQhpIa4OAXyWbNvEa+dOtLg0sH0rcDWnqu+O0Y2xD4ldin3138h3FOoRy36OohErbaAJBQurDUjtjg48ER4jYwgBt9BZmPDp7PWNv3oYTUMpcZKqZdgDabb1LTNb5AywyxX1b7xI+8LKSkxJrcEFow64m5ApAjYz7Iq8ttMiPFiAZU/I8KOZi0i9sHcqP5B27P46qJyBpUcHYyT32lGstOqKQKil7Fz7fy623csWYjL0jY7FovF09l0/ly6NsTKLLfonJFpvoDwkjK2oxvyCX3NxjLCK6BiPGf8VuZq8Eb7A/ollz0G7gA/wc+zc3vhF+jak02Nb9jpObPBrXYTS0JoqpgjEFdj9cB3EZgybVYc0WOIiNcQ0HcVfnbS2WSk7QlFbrPfFfydPnOqbhG/XK0pU=

Steps to reproduce

<script setup>
// App.vue
import { ref } from 'vue';
import Comp from './Comp.vue'
  
const show = ref(false);
</script>

<template>
  <Comp v-show="show" />
</template>
=======================
<script>
// Comp.vue
export default {
    inheritAttrs: false,
};
</script>
<template>
    <header v-bind="$attrs"></header>
  <footer></footer>
</template>

What is expected?

No warnings, because Vue3 supports multi-root components out-of-the-box.

What is actually happening?

[Vue warn]: Runtime directive used on component with non-element root node. The directives will not function as intended. 
  at <Comp> 
  at <Repl>

System Info

No response

Any additional comments?

v-if works correctly

avatar
Oct 6th 2022

I guess it is by design and not related to inheritAttrs. As you can see, vShow accepts a HTMLElement, instead of Fragment.

https://github.com/vuejs/core/blob/82e3f2dc3036b553261f302538701769fa92536e/packages/runtime-dom/src/directives/vShow.ts#L3-L10

avatar
Oct 6th 2022

v-show can only be used on single elements - or components witha single root element.

avatar
Oct 7th 2022

@LinusBorg Do we need to update Vue's official documentation?

avatar
Oct 7th 2022

It may indeed be worth adding a note about this to make it clearer.

You could add an issue in the docs repo and coordinte with the docs team where to best put that.

avatar
Oct 10th 2022

vue1.vue

<template>
  <div>
    <div id="target" v-bind="$attrs"></div>
  </div>
</template>
<script>
export default {
  name: "ee-navi",
  inheritAttrs: false,
}
</script>

vue2.vue

<template>
  <vue1 class="vue2"></vue1>
</template>
<style scoped>
.vue2 { font-size:100px }
</style>

the div id="target" has class="vue2" but not effective

avatar
Jul 27th 2023

Wouldn't it make sense to have some way to define directive target on multi-root components? Since v-bind="$attrs" already works fine in such cases for everything besides directives.