Reading the Vue Router documentation, the way to achieve route transitions is by doing:
<transition>
<router-view></router-view>
</transition>
But the problem is that VuePress is handling all the routing behind the scenes, so I can't figure out where to put that transition component.
Is there anyway to do this in VuePress?
You need to create your own theme or eject default.
In your Page.vue component wrap <Content /> component in <transition>
<transition name="fade">
<Content :custom="false"/>
</transition>
If you want to change something except <Content /> part, use binding
<transition name="header-fade" mode="out-in">
<header v-bind:key="$page.key">
<h1>{{ $page.title }}</h1>
</header>
</transition>
As far as I know –
Router transitions won't be possible, because as soon as you run 'vuepress build' the whole site will be static.
So no more routing is done and therefore the page will reload new content instead of dynamically adding it.
Related
I'm working on a project with Nuxt 3 and I keep getting this warning in the console
[Vue warn]: Component inside <Transition> renders non-element root node that cannot be animated.
at <Default >
at <AsyncComponentWrapper >
at <BaseTransition mode="out-in" appear=false persisted=false ... >
at <Transition name="layout" mode="out-in" >
at <Anonymous>
at <App key=1 >
at <NuxtRoot>
I dont have a transition yet but i think it's coming from nuxt spinner.
layouts/default.vue:
<template>
<TheHeader />
<slot />
</template>
I checked all my pages and components, all of them have only one root element of the following (header, nav, div, form, NuxtLink, button, img)
The warning doesn't specify where it's coming from and I don't know how to debug this.
In nuxt 3 everything should only have 1 root element:
<template>
<div>
<TheHeader />
<slot />
</div>
</template>
Just read the docs if you stuck on something: https://v3.nuxtjs.org/guide/directory-structure/layouts
If the transition isn’t in your code, I’d simply ignore the warning. As the warning states it will only cause non working animations for that specific component. I wouldn’t spent any time on debugging this since your code will be unaffected.
Edit:
If you really want to debug this, the easiest way is to use the Vue dev tools to search for the transition.
I want to use transition,keep-alive,router-view at the same time in App.vue. And I want the router's component not be reused.
This is the doc in vue-router
One thing to note when using routes with params is that when the user navigates from /users/johnny to /users/jolyne, the same component instance will be reused.
in Vue2.x,I can use key to keep router's component not be reused.
<transition>
<keep-alive>
<router-view :key="$route.fullPath" ></router-view>
</keep-alive>
</transition>
But in Vue3.0 the code is like below.
<router-view v-slot="{ Component }">
<transition>
<keep-alive>
<component :is="Component" />
</keep-alive>
</transition>
</router-view>
Someone can help to keep router's component not be reused in Vue3.0? use key in router-view cant work.
The answer was provided as a comment by Michal Levý:
Place :key="$route.fullPath" on <component>
I have a global sidebar component TheSidebar.vue:
<template>
<aside>
<slot></slot>
</aside>
</template>
In Blogs.vue (a page component) I try to register two components.
<template>
<div>
<h1>Experiences</h1>
<TheSidebar>
<SearchBlog />
<CategoryCheckboxFilter />
</TheSidebar>
<ExperienceList />
</div>
</template>
It seems like I cannot register two components in a slot?
Is this a good setup anyway and who do I have to achieve this?
Update
It's just working fine now and I can register more than one component in a <slot />. I think some webpack building issue before.
When I setup a typical route transition everything works as expected
<transition name="view" mode="out-in">
<router-view />
</transition>
But if I try to put the transition inside a view instead, the transition doesn't work
<template>
<transition name="view" mode="out-in">
<main>
<...>
</main>
</transition>
</template>
Any ideas why this could be the case?
The issue, seems to me, is that the <main> element is not entering or leaving, so it doesn't animate. You're probably trying to animate something within the <main> element which does not get targeted by the <transition> pseudo-element.
my suggestion is to encapsulate the element that's being toggled (v-if) or having visibility toggled (v-show) with transition
<template>
<main>
<transition name="view" mode="out-in">
<...something with a v-if or a v-show>
</transition>
</main>
</template>
Also, if you have are using a list/array (v-for) you should use transition-group
docs: https://v2.vuejs.org/v2/guide/transitions.html
I have a modal.vue component as follows:
<template>
<transition name="modal-transition">
<div class="modal-body" v-if="displayed">
<div class="modal-overlay" #click="displayed = false"></div>
<div class="modal-content">
<slot/>
</div>
</div>
</transition>
</template>
How do I mount this component to the applications root element rather than in place?
For crude inaccurate example:
<body>
<div id="app">
<div class="header"></div>
<div class="nav"></div>
<div class="stage">
<div class="sub-nav"></div>
<div class="content">
<modal :display.sync="display">MY MODAL</modal> <-- Don't mount here...
</div>
</div>
<-- Mount here instead...
</div>
</body>
The current issue is that my sites header and navigation is layered on top of my modal and it's darkened full screen overlay instead of layered behind the modal overlay.
Update for Vue 3
There is now a built in feature called teleport which allows mounting parts of your component template to any DOM element.
The example from the OP would look like something like this
<!-- MyModal.vue -->
<template>
<transition name="modal-transition">
<div class="modal-body" v-if="displayed">
<div class="modal-overlay" #click="displayed = false"></div>
<div class="modal-content">
<slot/>
</div>
</div>
</transition>
</template>
<!-- SomeDeeplyNestedComponent.vue -->
<template>
<teleport to="#app">
<!-- Can still receive props from parent -->
<MyModal :my-prop="foo">
<!-- slot content -->
</MyModal>
</teleport>
</template>
Vue 2
Move the elements own self to the element of applications root may be achieved in two ways, Using a portal as a preferred solution or using an append.
Using a Portal (Preferred Method)
PortalVue is a set of two components that allow you to render a
component's template (or a part of it) anywhere in the document - even
outside the part controlled by your Vue App!
https://portal-vue.linusb.org/
Using an Append (Not best practice)
If adding a portal library is too heavy, using an append is allowed but lightly discouraged officially in the VUE docs.
Typically this particular mount position will satisfy a z-index overlay for your own modal or dialog popup that you require to render over the top of the entire app. You can always substitute this.$root.$el in this example for a different element target using standard getElementBy or querySelector functions.
Here the element is being moved not destroyed and re-added, all reactive functionality will remain in tact.
<script>
export default {
name: 'modal',
...
mounted: function() {
this.$root.$el.append(this.$el);
},
destroyed: function() {
this.$el.parentNode.removeChild(this.$el);
}
}
</script>
On mounted the element is moved inside of where the top level VUE app instance is mounted.
On destroyed removes the placeholder DOM comment for the migrated component from the new parent to prevent orphaned duplication each time the component remounts it's self.
VUE officially states not to destroy an element outside of VUE so this is not to be confused with that statement, here the component has already been destroyed.
This DOM comment duplication will typically happen when for example switching views with vue-router as this mechanism mounts and dismounts all components in a router view each time vue-router view state changes.
This behaviour is a bug cause by vue-router, the object is destroyed properly by VUE render manager but an index reference remains by mistake, using a portal package resolves this issue.
Here is the result: