In essence, I'm looking to be able to render content from a component's declaration in the actual component itself.
Another component:
<Page>
<h1>A title</h1>
<p>An amazing paragraph</p>
</Page>
Page component:
<template>
<Header/>
<!-- Here is where I want to render the title & paragraph-->
<Footer/>
</template>
Vue does a similar function with the router's view, by exposing <router-view/> in the app's entry point. That's essentially what I would like to do except throughout components.
Is this at all possible?
You just need to add <slot/> there:
<template>
<Header/>
<slot></slot>
<Footer/>
</template>
Check out: https://v2.vuejs.org/v2/guide/components-slots.html
Related
I'm working on a Vue2 app.
It consists of a base template (App.vue) that looks like this:
<template>
<v-app>
<div id="app">
<NavigationBar></NavigationBar>
...
</div>
</v-app>
</template>
And various components (i.e., Home.vue, Login.vue, Navigation.vue etc...)
Being part of the main template, the NavigationBar is displayed in each component.
I would love to remove the NavigationBar only in the Login.vue component.
What could be the best way to achieve this?
Thanks
I understand paradigm "Page-component" but what if I have a page that renders component, how do I call another component inside this component? Currently nuxtjs does not allow me do it. I can not stick to standart "page-component" scheme as I am bulding cart which calls cart-items.
Say If a cart component which is called by page looks like this, how would it call cart-item component inside it?
<!---- cart component called from index.vue --->
<template>
<div>
<Cart-item></Cart-item> < ---------- This doesn't work.
</div>
</template>
<script>
export default {
props: ['items']
}
</script>
I managed it the standard way:
<template>
<div>
<CartItem></CartItem>
</div>
</template>
<script>
import CartItem from '../components/Cart-item'
export default {
props: ['items']
}
</script>
Since nuxtjs auto-registers all components wonder if there is more graceful way.
EDIT: as promised, here is an example on how to pass some content to a component from another one thanks to slots. This is totally working in any Nuxt page ofc.
NestedContent.vue
<template>
<div>
<p>Here is the NestedContent component and below is a slot passed to ParentWithSlots' component</p>
<hr />
<parent-with-slots>
<!-- <template #default> // this one can be omit since we do use the default slot here -->
<p>This content is inserted into the component ParentWithSlots</p>
<!-- </template> -->
</parent-with-slots>
</div>
</template>
ParentWithSlots.vue
<template>
<div>
<p>xxxxxxxxxxx ParentWithSlots' content before slot xxxxxxxxxxx</p>
<slot>Default content in case none is provided</slot>
<p>xxxxxxxxxxx ParentWithSlots' content after slot xxxxxxxxxxx</p>
</div>
</template>
Here is how it looks
PS: you may also give a try to layouts, it can be useful for overall positioning of some of your components visually.
If your components are in the components directory, you can set components: true in your nuxt.config.js and have access to it pretty much anywhere without any additional step with the <cart-item></cart-item> syntax.
More details here: https://nuxtjs.org/blog/improve-your-developer-experience-with-nuxt-components/
If I have a layout component that contains a few slots, is it possible to have a component within layout populate those slots?
JS Fiddle
<div id="app">
<layout>
<page></page>
</layout>
</div>
const app = Vue.createApp({});
app.component('layout', {
template: `
<header>
<slot name="header"></slot>
</header>
<main>
<slot name="main"></slot>
</main>
`,
});
app.component('page', {
template: `
<!--
is there a way fill each slot of "layout"? i.e.
<template #header>
<h1>Page Header</h1>
</template>
<template #main>
<h1>Page Content</h1>
</template>
-->
`,
});
app.mount('#app');
It seems what I'm looking for is being referred to as template blocks in other places. This is not something Evan You (the creator of Vue) currently supports as he doesn't believe this functionality adds enough value for the added complexity.
Some interesting links:
Template blocks for component inheritence (proposed syntax)
Possible upcoming third-party package to achieve this
Example of using Pug with it's concepts of block and extends
I have an external div that I need to render inside my Vue app. I'm trying to use a slot, like but that's a no go as nothing renders.
Any ideas?
Goal is to have HTML like this (Vue mounts on #app):
<div id="app" data-slot-header="#header"></div>
<div id="header">
<h1>Title here</h1>
</div>
Then the Vue component
<template>
<div>
<slot name="header"></slot>
</div>
</template>
You can use a dynamic <component> and refer to your #header element as a template reference.
For example
new Vue({
data: () => ({
headerComponent: {
template: '#header' // refer to template element by selector
}
}),
}).$mount('#app')
#app:before,#header:before{position:absolute;top:0;right:0;color:rgba(1,1,1,.5);font-size:.8rem}#app{border:1px solid #666;position:relative}#app:before{content:'Vue app'}#header{position:relative;opacity:.5}#header:before{content:'Original header'}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<div id="app">
<p>Dynamic component rendered here 👇</p>
<component :is="headerComponent"></component>
</div>
<div id="header">
<h1>Title here</h1>
</div>
Slots are mainly used with reusable Vue components so that the parent component can render custom stuff inside designated sections of the child. The root component does not have a parent, so it doesn't make sense to use slots for this.
Why can't you just hard-code the div in the template? Or do you need it to be dynamic; will you be swapping out the header contents in some situations? Please provide more information about what your use-case is, otherwise my answer is "just hard-code it".
Take a look at portal-vue. It allows child components to render templates anywhere in the DOM. This might work for your situation.
I have a question about nuxt.js project,
as we know the nuxt.js generate the routes automatically.
I have a page structure like this:
In the header there is navigator in it, I want use it to switch pages(switch the main body's content).
but the nuxt.js do not like vue-router have <router-view/>
<route-link></route-link>
<router-view/>
it only has
<nuxt-link></nuxt-link>
So I write code structure like this:
<template>
<div >
<Header></Header> <!-- the main body written in the Header -->
<Footer></Footer>
</div>
</template>
the Header component:
<navigator-component></navigator-component>
<div>
<Home v-show="$store.state.page_name == 'home' "></Home>
<Search v-show="$store.state.page_name == 'search' "></Search>
<Aboutus v-show="$store.state.page_name == 'about_us' "></Aboutus>
<Contactus v-show="$store.state.page_name == 'contact_us' ">
</Contactus>
</div>
but there is a problem, the URL will not switch, it will stay in the root URL.
So, what's the appropriate way to solve my problem? how to design the
code structure?
Nuxt has a "router-view". It is just: <nuxt />.
The way to go here, is to use layouts.
There is a default file in the layouts directory. Every page has this layout by default.
You can simply write in this default layout file your page structure.
For example:
<template>
<Header />
<nuxt />
<Footer />
</template>
<script lang="ts">
import Vue from 'vue';
import Header from '..';
import Footer from '..';
export default {
components: {
Header,
Footer,
},
};
</script>