Closed davidlueder closed 2 years ago
Hi David!
While pages can only currently provide a default slot, layouts can provide several slots to parent layouts.
That usually covers plenty of ground, given that you can use page-specific information in layouts by using $frontmatter
and $meta
.
Would you share a real-life use case where it would be convenient to use several slots at the page level?
Hi Máximo, in my opinion this would be helpful if someone wants to split content in different sections on the layout level. I think the definition of a layout itself requires the option to fill different slots: "the way in which the parts of something are arranged or laid out".
Maybe this is the reason that even the vuejs documentation uses a "BaseLayout" as an example for multiple named slots: https://vuejs.org/guide/components/slots.html#named-slots
When we define a Layout like this:
<template>
<header>
<slot name="header-content" />
</header>
<nav>
<!-- Navigation etc... -->
</nav>
<div class="container">
<aside>
<slot name="side-content" />
</aside>
<main>
<slot />
</main>
</div>
</template>
It can be styled on the layout level and the content of a page could be separated.
Sure, there are other options. For example, someone might (mis)use (like in the vuejs docs) a component for that:
<template>
<FakeLayoutComponent>
<template #header-content> ... </template>
<template #side-content> ... </template>
<template> ... </template>
</FakeLayoutComponent>
</template>
Using $frontmatter
and $meta
is a great option for simple things like title, author and other information about the page. As far as i know you could even use a frontmatter parameter for html code, but that really doesn't feel right.
I implemented a proof-of-concept, which enables .vue
pages to pass slots to the parent layout using the standard syntax:
<template>
<template #header>
<h2>Important headline</h2>
</template>
<p>Other content</p>
</template>
The only downside is that it requires an additional SFC parse of .vue
pages on each pass so it's a bit slower (although it's only a few ms). I'd like to benchmark it in a slower computer before deciding to go ahead with this change.
Please give it a try, and let me know how it goes 😃
That was really fast... I will try to test this tomorrow!
Closing for now as I haven't found any implementation without serious downsides, see #114 for further details.
If you need to provide HTML to layouts, you can use the following pattern:
src/layouts/default.vue
<template>
<header><slot name="header">Welcome</slot></header>
<main><slot/></main>
</template>
Opt-out of the default layout using layout="false"
, and add an existing layout to the template, passing named slots as usual.
<template layout="false">
<DefaultLayout>
<template #header>I'm on the header!</template>
I'm on the main section!
</DefaultLayout>
</template>
Have in mind that iles automatically exposes existing layouts using the <${Name}Layout>
convention, no need to import them.
It's not as terse as the proof-of-concept, but it's not too bad either.
Hi, i would like to use layouts with multiple slots but did not find a way to reference any named slots from within a page.
Example (layout/default.vue):
Vue pages can only contain a single
<template>
tag, maybe a custom component that works like like<Head>
could be the solution.Example (pages/index.vue):