Чтобы проиллюстрировать то, что я пытаюсь достичь, а также обсудить и изучить каждый механизм в отдельности, я разделил проблему на две независимые задачи:
1. Держите предыдущий маршрут видимым, пока новый маршрут не перейдет в
Независимо от того, является ли переход скользящим, то, что я пытаюсь здесь, или просто исчезаю;Режим in-out
не работает так, как я ожидал, а именно, что существующий маршрут остается видимым до тех пор, пока следующий маршрут не завершит свой переход (например, наложился поверх предыдущего), в точности так, как показано здесь в последнем примере этого раздела. https://vuejs.org/v2/guide/transitions.html#Transition-Modes, показывает две кнопки в режиме in-out
. Вместо этого никакого перехода не происходит, но он просто переворачивает маршруты статически в половине заданного времени перехода.
Есть ли какие-либо предостережения с маршрутами и очевидная причина, почему это не будет работать так же, например, что одинrouter-view
может удерживать только один, и поэтому вход невозможен?
РЕДАКТИРОВАТЬ 1:
Я понял, что in-out
будет на самом деле толькоработайте с position:absolute
на обоих элементах, иначе они не будут наложены. Любая идея, как я мог бы элегантно включить такое поведение, потенциально устанавливая эту абсолютную позицию только во время перехода маршрутизатора?
Текущий взлом, который имеет визуальный эффект модального сдвига (mode: in-out) Я смотрюдля: добавление style="position:absolute; z-index:2100"
к маршруту диалога. Затем мне нужно изменить базовый переход после его показа, чтобы получить эффект обратного скрытия (mode: out-in).
Также см. EDIT 2 ниже.
2. Создание модальной страницы (маршрута), которая открывается над другой существующей страницей при переходе к
Я попытался взломать это поведение, добавив второй вид маршрутизатора в App.vue
<router-view />
<router-view name="dialog" />
Определенный компонент добавляется к моим маршрутам, как этот
{
path: 'records/new',
components: {
dialog: () => import('layouts/NewRecord.vue')
},
children: [
{
name: 'new-record',
path: '',
component: () =>
import('src/pages/NewRecord.vue')
}
]
}
Я не уверен, имеет ли этот подход смысл, но я не мог заставить его работать должным образом. Цель состоит в том, чтобы просто наложить еще один router-view name="dialog
всякий раз, когда нажимается «диалоговый» путь, поэтому, пока он может быть анимирован (сдвигается вверх), другой вид маршрутизатора остается видимым ниже. В конце концов, я думаю, что я столкнулся с той же проблемой: после изменения маршрута начальный вид маршрутизатора отбрасывает свой компонент, поскольку путь больше не соответствует текущему местоположению.
В любом случае, есть людис большим опытом и знаниями, поэтому я надеюсь, что смогу проиллюстрировать то, чего я пытаюсь достичь, и мне просто любопытно и благодарно прочитать ваши материалы.
РЕДАКТИРОВАТЬ 2
Я мог бы заставить его работать так, как я хотел, просто с одним, обернутым в пользовательский page-transition
компонент. Хотя это и есть хак, и мне нужно было добавить position: absolute
к майским макетам страниц, ко всем из них (как компоненту «уходящий», так и «входящий» нужно position: absolute
) при показе компонента диалога. Я уверен, что есть лучший способ, но я пока не нашел его.
Пользовательский компонент перехода страницы:
<template>
<transition :name="name" :mode="mode">
<slot/>
</transition>
</template>
<script lang="ts">
import { Component, Watch } from 'vue-property-decorator'
import Vue from 'vue'
import { Route } from 'vue-router'
@Component({
components: {}
})
export default class PageTransition extends Vue {
NAME_FADE = 'fade'
NAME_SLIDE_UP = 'slide-up'
NAME_SLIDE_DOWN = 'slide-down'
MODE_OUT_IN = ''
MODE_IN_OUT = 'in-out'
name = this.NAME_FADE
mode = this.MODE_OUT_IN
@Watch('$route', { immediate: true, deep: true })
onRouteChanged(newVal: Route, oldVal: Route) {
if (newVal.meta.transition === 'dialog') {
this.name = this.NAME_SLIDE_UP
this.mode = this.MODE_IN_OUT
} else if (oldVal && oldVal.meta.transition === 'dialog') {
this.name = this.NAME_SLIDE_DOWN
// shift next page in immediately below dialog
this.mode = this.MODE_IN_OUT
} else {
// default
this.name = this.NAME_FADE
this.mode = this.MODE_OUT_IN
}
}
}
</script>
<style lang="scss" scoped>
.fade-enter, .fade-leave-to {
opacity: 0;
}
.fade-enter-active, .fade-leave-active {
transition: all 0.1s ease;
}
// start of enter element
.slide-up-enter {
transform: translateY(60%);
opacity: 0;
}
.slide-up-enter-active {
transition: all 0.3s ease-out;
z-index: 2100;
}
// start of leave element
.slide-up-leave, .slide-up-leave-active {
opacity: 0;
}
// start of leave element
.slide-down-leave {
z-index: 2100;
}
.slide-down-leave-to {
transform: translateY(60%);
opacity: 0;
z-index: 2100;
}
.slide-down-leave-active {
transition: all 0.3s ease-in;
}
// start of enter element
.slide-down-enter {
opacity: 0;
}
.slide-down-enter-active {
/* show immediately behind existing page (lower z-index) */
transition: all 0s;
}
</style>