In the Vue documentation of the template
option for the Vue constructor it is stated, that content of the root element is not displayed "unless content distribution slots are present in the template". However when trying to write something like:
new Vue({
el: '#app',
template: `
<div>
<h1>App title</h1>
<slot></slot>
</div>
`
});
<html>
<body>
<div id="app">
App content
</div>
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
</body>
</html>
The content from the root element is not included, what is the right way to do it?
Or what is the suggested way to inject additional content programmatically when creating the vue instance?
In some aspects, the root does not behave like a regular component: you can't pass props
, nor use <slot>
s directly in its template (related: vue/#4485).
Have a look at the current source: the $slots
are resolved by the resolveSlots
function, and at the point resolveSlots
is called on the root component its $options._renderChildren
is undefined
, so no slots are resolved. Not that it matters after that point, but, effectivelly, the root component never populates its $options._renderChildren
.
It's been said that the <slot>
handling logic complicates things a bit, so that probably was a design decision.
The pattern commonly used to handle what you are asking is just wrapping the content in another component (say <app>
) component and going from there.
Vue.component('app', {
template: `<div>
<h2>I'm the <app> component title</h2>
<slot>app slot default text</slot>
</div>`
});
new Vue({
el: '#app'
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
<app>
I'm the contents of app's template and was declared in root
</app>
</div>
See how this.$slots
is not populated for root even though it has <slot>
s in the demo below.
Vue.component('app', {
template: `<div>
<h2>I'm the <app> component title</h2>
<slot>app slot default text</slot>
</div>`,
created() {
console.log("<app>'s VDOM children (LENGTH): ", this.$options._renderChildren.length);
console.log("<app>'s slots (LENGTH): ", this.$slots.default.length);
}
});
new Vue({
el: '#app',
created() {
console.log("root's VDOM children: ", this.$options._renderChildren);
console.log("root's slots: ", this.$slots);
}
});
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<div id="app">
<app>
I'm the contents of app's template
</app>
<slot>root's slot's default content, won't make it into $slots, check the console</slot>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With