まとめVueの2つの異なるルータービューにまたがるアニメーションを作成するためのソリューションを探しています。私が遭遇した問題は、ブラウザが別のルータービューに変わると、ページが再レンダリングされることです。そのため、ブラウザが再レンダリングするとアニメーションは消えます。
アニメーション
基本的に、アプリにはホームページとアバウトページの2つの異なるページがあります。ユーザーが青いメニューボタンをクリックすると、画面全体が表示されるまで、緑のナビゲーションメニューが左から右にスライドします。このメニューには、aboutとhomeの2つのリンクがあります。ユーザーが「約」をクリックすると、白いオーバーレイが左から移動して画面全体を覆い、次に右に移動して消えます。アバウトページは消えた後に表示されます。これは、私が達成したいアニメーション効果を実証するコーデックの例です(このデモではルーターを使用していません)。https://codepen.io/wl1664209734/pen/qBamXEL
以下は、codepenのvueテンプレートでアニメーションを再作成するためのコードです。
<template>
<div class="wrap">
<!--Transition Overlay -->
<transition
name="page-shift"
enter-active-class="animate__animated animate__slideInLeft animate__faster"
leave-active-class="animate__animated animate__slideOutRight animate__faster"
>
<div v-if="showOverlay" class="overlay"></div>
</transition>
<!--Navigation Menu -->
<transition
name="slide"
enter-active-class="animate__animated animate__slideInLeft animate__faster"
leave-active-class="animate__animated animate__slideOutLeft animate__faster"
>
<div v-if="menuOpen" class="navigation">
<div
class="container h-100 d-flex justify-content-center align-items-center"
>
<div class="text-center">
<h3 class="font-weight-bold text-light" @click="pageShiftToHome">
HOME
</h3>
<h3 class="font-weight-bold text-light" @click="pageShiftToAbout">
ABOUT
</h3>
</div>
</div>
</div>
</transition>
<!--NavBar -->
<div class="navbar d-flex justify-content-end">
<div
@click="menuOpen = !menuOpen"
class="nav-link font-weight-bold mt-3 btn btn-primary"
>
Menu
</div>
</div>
<!--Home Page -->
<div
v-if="showHomePage"
class="homepage d-flex justify-content-center align-items-center"
>
<h1 class="text-light">HOME</h1>
</div>
<!--About Page -->
<div
v-if="showAboutPage"
class="aboutpage d-flex justify-content-center align-items-center"
>
<h1 class="text-light">ABOUT</h1>
</div>
</div>
</template>
<script>
export default {
data() {
return {
menuOpen: false,
showHomePage: true,
showAboutPage: false,
showOverlay: false
};
},
methods: {
pageShiftToHome: function () {
this.showOverlay = !this.showOverlay;
const _this = this;
setTimeout(function () {
_this.menuOpen = !_this.menuOpen;
_this.showAboutPage = false;
_this.showHomePage = true;
}, 500);
setTimeout(function () {
_this.showOverlay = !_this.showOverlay;
}, 1000);
},
pageShiftToAbout: function () {
this.showOverlay = !this.showOverlay;
const _this = this;
setTimeout(function () {
_this.menuOpen = !_this.menuOpen;
_this.showHomePage = false;
_this.showAboutPage = true;
}, 500);
setTimeout(function () {
_this.showOverlay = !_this.showOverlay;
}, 1000);
}
}
};
</script>
<!-- Use preprocessors via the lang attribute! e.g. <style lang="scss"> -->
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
background: #292929;
}
.wrap {
width: 100%;
height: 100vh;
background: #292929;
.overlay {
width: inherit;
height: inherit;
background: #fff;
position: absolute;
z-index: 999;
}
.navigation {
width: inherit;
height: inherit;
background: #3ecc28;
position: absolute;
z-index: 111;
h3 {
cursor: pointer;
}
}
.navbar {
width: 100%;
z-index: 333;
.nav-link {
color: #fff;
cursor: pointer;
border: 0;
}
}
.homepage {
width: inherit;
height: inherit;
position: absolute;
top: 0;
left: 0;
}
.aboutpage {
@extend .homepage;
}
}
</style>
私のコードの説明
ここにcodeSandboxリンクがあります、私はこのサンドボックスで問題を再現します、これは人々が私の問題をよりよく理解するのを助けると思います。https://codesandbox.io/s/vue-page-shift-anime-yp1yf
このサンドボックスでは、vueテンプレートを使用しました。これには、App.vueという1つの主要コンポーネントと、Homepage.vue、Aboutpage.vue、Background.vue、Navbar.vue、Navigation.vueという5つの他のコンポーネントが含まれています。背景には含まれていナビゲーションバーとナビゲーションをアプリのための静的な要素を形成します。両方のホームページとAboutpageを有する背景とユニークなヘッダ。ホームページのヘッダーはHOMEで、AboutpageのヘッダーはABOUTです。次に、main.jsでルーターを構成し、App.vueにrouter-viewタグを配置します。また、Navigation.vueにrouter-linkを追加します。クリックイベント(ページシフト)をルーターリンクに追加すると、このイベントはBackground.vueに発行されます。したがって、ユーザーがリンクをクリックすると、Background.vueのpageShiftメソッドが呼び出され、アニメーションが発生します。
* Main.js
import Vue from "vue";
import App from "./App.vue";
import VueRouter from "vue-router";
import "bootstrap/dist/css/bootstrap.css";
import "animate.css";
import Homepage from "./components/Homepage";
import Aboutpage from "./components/Aboutpage";
Vue.use(VueRouter);
Vue.config.productionTip = false;
const router = new VueRouter({
routes: [
{
path: "*",
component: Homepage
},
{
path: "/about",
component: Aboutpage
}
]
});
new Vue({
render: (h) => h(App),
router
}).$mount("#app");
*アプリを見る
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "App",
};
</script>
<style>
body {
background: #292929;
}
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</style>
* Background.vue
<template>
<div class="wrap">
<transition
name="page-shift"
enter-active-class="animate__animated animate__slideInLeft animate__faster"
leave-active-class="animate__animated animate__slideOutRight animate__faster"
>
<div v-if="showOverlay" class="overlay"></div>
</transition>
<navigation :menuOpen="menuOpen" @page-shift="pageShift" />
<navbar @open-menu="menuOpen = !menuOpen" />
<div>
<div class="page d-flex justify-content-center align-items-center">
<h1 class="text-light">{{ header }}</h1>
</div>
</div>
</div>
</template>
<script>
import Navbar from "./Navbar";
import Navigation from "./Navigation";
export default {
name: "background",
props: ["header"],
data: function () {
return {
menuOpen: false,
showOverlay: false,
};
},
components: {
Navbar,
Navigation,
},
methods: {
pageShift: function () {
this.showOverlay = !this.showOverlay;
const _this = this;
setTimeout(function () {
_this.menuOpen = !_this.menuOpen;
}, 500);
setTimeout(function () {
_this.showOverlay = !_this.showOverlay;
}, 1000);
},
},
};
</script>
<style lang="scss" scoped>
.wrap {
width: 100%;
height: 100vh;
.overlay {
width: inherit;
height: inherit;
background: #fff;
position: absolute;
z-index: 999;
}
.page {
width: 100%;
height: 100vh;
position: absolute;
top: 0;
left: 0;
}
}
</style>
*Navbar.vue
<template>
<div class="navbar d-flex justify-content-end">
<div
@click="$emit('open-menu')"
class="nav-link font-weight-bold mt-3 btn btn-primary"
>
Menu
</div>
</div>
</template>
<script>
export default {
name: "navbar",
};
</script>
<style lang="scss">
.navbar {
width: 100%;
z-index: 333;
.nav-link {
color: #fff;
cursor: pointer;
border: 0;
}
}
</style>
* Navigation.view
<template>
<transition
name="slide"
enter-active-class="animate__animated animate__slideInLeft animate__faster"
leave-active-class="animate__animated animate__slideOutLeft animate__faster"
>
<div v-if="menuOpen" class="navigation">
<div
class="container h-100 d-flex justify-content-center align-items-center"
>
<div class="text-center">
<router-link to="/*" class="font-weight-bold text-light"
><h3 @click="$emit('page-shift')">HOME</h3></router-link
>
<router-link to="/about" class="font-weight-bold text-light"
><h3 @click="$emit('page-shift')">ABOUT</h3></router-link
>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: "navigation",
props: ["menuOpen"],
};
</script>
<style lang="scss" scoped>
.navigation {
width: 100%;
height: 100%;
background: #3ecc28;
position: absolute;
z-index: 111;
top: 0;
left: 0;
a:hover {
text-decoration: none;
}
span {
cursor: pointer;
}
}
</style>
* Homepage.vue
<template>
<background :header="'HOME'" />
</template>
<script>
import Background from "./Background";
export default {
name: "homepage",
data: function () {
return {
menuOpen: false,
};
},
components: {
Background,
},
};
</script>
<style lang="scss" scoped>
</style>
Aboutpage.vue
<template>
<background :header="'ABOUT'" />
</template>
<script>
import Background from "./Background";
export default {
name: "aboutpage",
data: function () {
return {
menuOpen: false,
};
},
components: {
Background,
},
};
</script>
<style lang="scss" scoped>
</style>
私が発見した問題は、同じルータービューにとどまると、アニメーションが発生することです。別のビューに移動すると、ページが再レンダリングされてすべてがリロードされるため、アニメーションはまったく発生しません。たとえば、サンドボックスで、現在家にいて、家をクリックすると、アニメーションが表示されます。ただし、ホームから約に切り替えると、ページが再読み込みされ、アニメーションが失敗します。
私が試したことは、Vueは初めてです。解決策の1つは、異なるビューを切り替えるときにページがレンダリングされないようにすることだと思います。私はそれを達成する方法がわかりません。App.vueのrouter-viewタグの周りにtransitionタグを使用しようとしましたが、理想的なアニメーションが得られません。私もキープアライブを試しましたが、まったく機能しません。私の説明が理にかなっていることを願っています、そして私はあなたの解決策を楽しみにしています!ありがとう!
問題は、を介してビュー内にナビゲーションを含めていることですBackground.vue
。そうしないでください。に含めますApp.vue
。
ルートが変更されると、<router-view />
のコンテンツには、そのルートのコンポーネントの新しいインスタンスが入力されます((または)のroutes
配列で設定されます)。したがって、代わりに:router/index.ts
.js
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
...あなたApp.vue
は含むべきです:
<template>
<div id="app">
<navigation />
<router-view />
</div>
</template>
ページが変更されたときに再レンダリングしたくないページの他の部分(サイドバー、フッターなど)がある場合は、それらも中に含めますApp.vue
。したがって、フッターとサイドバーを使用すると、次のようになります。
<template>
<div id="app">
<header>
<navigation />
</header>
<main>
<sidebar />
<router-view />
</main>
<footer />
</div>
</template>
ルートが変更<router-view />
されると、再レンダリングされるだけで、ルートに設定されたアニメーションがそれに応じて実行されます。直接配置された他のレイアウト要素はApp.vue
再レンダリングされません。明らかに、現在のルートに基づいてコンテンツを動的に変更すると、それらのパーツは更新されますが、ベースのDOM要素は同じままです。
暗黙的に、に<navigation />
直接配置することを決定した他のものと一緒に、ビューから削除する必要がありますApp.vue
。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加