シナリオは次のとおりです。
- vue-router で再利用される Page コンポーネントがあります
- この Page コンポーネントには、現在のページに応じて、Element1 または Element2 の動的コンポーネントが含まれます。
親ルートが変更されたときに、この動的にネストされたコンポーネントで終了遷移をトリガーするにはどうすればよいですか?
以下のコードで動作するはずですが、ページを変更するpage beforeRouteLeave
とelement leave
コンソールに出力されません。
------ BUG: never fired -----
(コードの 3x 部分を参照)
const Index = {
template: `<div id="app">
<router-link :to="{ path: '1' }">page 1</router-link> |
<router-link :to="{ path: '2' }">page 2</router-link>
<router-view :key="'a' + $route.params.id"></router-view>
</div>`
};
const Element1 = {
template: `<transition @enter="transitionEnter" @leave="transitionLeave">
<div class="element" v-show="show">Element 1</div>
</transition>`,
props: {
show: Boolean
},
methods: {
transitionEnter(el, done) {
console.log('element 1 enter')
done()
},
transitionLeave(el, done) {
console.log('------ BUG: never fired -----')
console.log('element 1 leave')
done()
}
}
};
const Element2 = {
template: `<transition @enter="transitionEnter" @leave="transitionLeave">
<div class="element" v-show="show">Element 2</div>
</transition>`,
props: {
show: Boolean
},
methods: {
transitionEnter(el, done) {
console.log('element 2 enter')
done()
},
transitionLeave(el, done) {
console.log('------ BUG: never fired -----')
console.log('element 2 leave')
done()
}
}
};
const Page = {
template: `<transition @enter="transitionEnter" @leave="transitionLeave">
<div>
<p>page {{ id }}</p>
<component :is="element" :show="elementShow"></component>
</div>
</transition>`,
components: {
Element1,
Element2,
},
data() {
return {
id: this.$route.params.id,
elementShow: false,
}
},
computed: {
element() {
return 'Element' + this.id
}
},
methods: {
transitionEnter(el, done) {
console.log('page', this.id, 'enter');
done();
},
transitionLeave(el, done) {
console.log('page', this.id, 'leave');
done();
},
},
mounted() {
this.elementShow = true
},
beforeRouteLeave(to, from, next) {
console.log('------ BUG: never fired -----')
console.log('page beforeRouteLeave')
this.elementShow = false
setTimeout(next)
},
};
const App = Vue.extend(Index);
const router = new VueRouter({
routes: [{
path: '/:id',
component: Page
}, {
path: '*',
redirect: '/1'
}]
})
const app = new App({ router }).$mount('#app');
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app"></div>