Reputation: 30656
After reading the documentation on slots I've come away not really understanding why they are useful, because it seems they function exactly opposite of what I need to do.
For those familiar with ASP.NET, what I really want is an @section
. That is I have my main page layout defined in some component, and within that component I want to control one small section from within the child where the hierarchy of markup does not make this easy.
I want to have basically this same markup in my application as in the docs:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
The issue is that I want this to live in my higher level component, and then within the child I want to specify the content that goes in header, for example:
<template>
<div>
<h1 slot="header">Name Of This Page {{ DataFromChildContext }}</h1>
<div id="remainder-of-child">
<!snip...-->
</div>
</div>
</template>
The documentation is pretty clear, this goes in the PARENT:
To provide content to named slots, we can use the slot attribute on a element in the parent:
emphasis mine
Am I barking up the wrong tree or is there a way to make this work using native VueJS features? I want to define the content of the slots in the child and the slot space in the parent.
Upvotes: 3
Views: 1180
Reputation: 43899
A slot
is not a parent-child relationship. It is a space to contain (but not control) arbitrary content. It is useful for writing presentation components, like a dialog, where you want the component to control all the dialog-y behavior, but it doesn't matter what the contents of the dialog are (and they may have behaviors of their own).
If you have a child component, you don't use a slot
, you just write it in the template. Which is to say, you may be overthinking this (or I may not understand what you're trying to achieve).
<div class="container">
<header>
<header-child></header-child>
</header>
Upvotes: 1
Reputation: 36349
I think what you're really looking for is named views, provided by VueRouter.
As an example:
<div id="app">
<h1>Named Views</h1>
<ul>
<li>
<router-link to="/">/</router-link>
</li>
<li>
<router-link to="/other">/other</router-link>
</li>
</ul>
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
</div>
And in the router code:
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
const Baz = { template: '<div>baz</div>' }
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/',
// a single route can define multiple named components
// which will be rendered into <router-view>s with corresponding names.
components: {
default: Foo,
a: Bar,
b: Baz
}
},
{
path: '/other',
components: {
default: Baz,
a: Bar,
b: Foo
}
}
]
})
new Vue({
router,
el: '#app'
})
I recognize that in ASP.NET that's not how you do it (in that the page directly renders the sections, rather than the router logic), but I think it's as close as you'll get in Vue.
Upvotes: 2
Reputation: 35724
Slots offer an easier way to create reusable components. For example, a modal, where you can define the header and body, or some other ui widget like a custom button.
The design of Vue (and other FE/JS frameworks) is data driven, and the data flows from top down.
It sounds like what you're looking for, is that a action/data that originates at the bottom affects changes at the top level. The way to do this is to make the data available at the top level. There are plugins that can help with these cases, such as vuex and route. Vuex provides a globally accessible store, so one component can make a change, and another component can listen for that change, and it doesn't matter what the relationship is. Router is used to manage navigation between pages, and allows to easily define which component should be shown within a context of a template. You can create your own implementation too, using listeners and emit, a global bus, or even passing a function as a prop.
Upvotes: 1