Why doesn't <router-view /> want to be displayed inside <component>? - vue.js

I switched after vue 2 to vue 3 and I can't understand why doesn't display anything inside and how can I make it work
That's how it works
<template>
<component :is="layout"></component>
<router-view />
</template>
That's not how it works
<template>
<component :is="layout">
<router-view />
</component>
</template>

Related

Keep alive stops working when adding div with :key

I am currently facing an issue where the <keep-alive> stops working after adding a :key to the parent <div>. This <div> and also the :key is needed, otherwise the <transition> won't work. Anyone got a solution for that?
Sorry i am not able to provide more code.
<template>
<router-view v-slot="{ Component, route }">
<transition :name="transitionName">
<div :key="route.name">
<keep-alive include="SpecialComponent">
<component :is="Component" />
</keep-alive>
</div>
</transition>
</router-view>
</template>
It looks like even putting you component in a div alone prevents transitions.
My test app components inside a div didn't do any transitions even if I don't use <keep-alive> and :key.
Why do you need to wrap it in a div?
Shouldn't it work so?
<transition :name="transitionName">
<keep-alive include="SpecialComponent">
<component :is="Component" :key="route.name" />
</keep-alive>
</transition>

Display a specific route in a different router-view

I've got a Vue 3 app with Vue Router 4 and I want to achieve this:
<template>
<v-app>
<router-view></router-view> //This is where login would be
<app-layout>
<router-view /> //Everything else
</app-layout>
</v-app>
</template>
<script lang="ts" setup>
import AppLayout from "./components/AppLayout.vue";
</script>
I've got an <app-layout> component which includes navbar and a sidebar, but I don't want to display those when the user is not logged in. I also don't want to wrap each component in <app-layout> individually.
Is there a way I can achieve this?
You can use the Vue-router's v-slot API like this :
<template>
<v-app>
<router-view v-slot="{ Component, route }">
<component v-if="route.name === 'Login'" :is="Component" />
<app-layout v-else>
<component :is="Component" />
</app-layout>
</router-view>
<!-- Or -->
<router-view v-slot="{ Component, route }">
<component :is="route.name === 'Login' ? 'template' : 'app-layout'">
<component :is="Component" />
</component>
</router-view>
</v-app>
</template>
<script lang="ts" setup>
import AppLayout from "./components/AppLayout.vue";
</script>
And in your router, for the login route, don't forget to add the route name :
{
name: 'Login', // important
// ...
}

How to pass prop from page to layout

I currently have duplicated layout that the only difference is a prop I pass to a component:
default.vue
<template>
<div class="page">
<SkipToContent />
<Header />
<Nuxt />
<Footer />
</div>
</template>
front.vue
<template>
<div class="page">
<SkipToContent />
<Header light="true" />
<Nuxt />
<Footer />
</div>
</template>
Is there any way to pass that light: true from page to layout so I can use only default.vue layout?
I know I could emit some event on mounted but would like to prevent using lifecycle hooks
Passing data up from a child is ideally done by emitting events, and you don't need to use lifecycle hooks for that (a custom event listener would work).
But I think a cleaner solution would be to factor out the common markup into a component that receives a light prop, and use them in both layouts:
<!-- components/CommonLayout.vue -->
<template>
<div class="page">
<SkipToContent />
<Header :light="light" />
<Nuxt />
<Footer />
</div>
</template>
<script>
export default {
props: {
light: Boolean,
}
}
</script>
<!-- layouts/default.vue -->
<template>
<CommonLayout />
</template>
<!-- layouts/front.vue -->
<template>
<CommonLayout light />
</template>
demo

Nested Vue router-view transition not reacting when navigating

Here is code example:
https://jsfiddle.net/9jypnkue/
The transition v-on:enter="enter" for the nested view is not called when also the main router-view is transitioning.
<router-view ref="nestedView" v-slot="{ Component }">
<transition v-on:enter="enter">
<component :is="Component"/>
</transition>
</router-view>
I would like both animations being called simultaneously.
Using Vue 3 and Vue Router 4 release candidate/beta.
Adding 'appear' to the router fixes it:
<router-view ref="nestedView" v-slot="{ Component }" appear>
<transition v-on:enter="enter">
<component :is="Component"/>
</transition>
</router-view>
https://jsfiddle.net/27qae5zj/1/

Load Component with Vue Router

I want to load 3 Components at a time like that:
<app-header />
<app-main />
<app-footer />
But I want to load Router View also in this page.
<app-header />
<router-view />
<app-footer />
While I will click on the router-link then <app-main /> will be vanish and <router-view /> will be visible.
Is there any better way to handle it without if or show?
You can pass router-view via slot to your app-main component like this:
<app-header />
<app-main>
<router-view/>
</app-main>
<app-footer />
Also you need to insert a slot tag in your app-main component like this:
<template>
<!-- your code -->
<slot></slot>
<!-- ... -->
</template>
For more details visit https://v2.vuejs.org/v2/guide/components-slots.html