Vue Router beforeRouteLeave не останавливает субкомпоненты
У меня простой вопрос. Я просто хочу отменить подкомпонент при изменении маршрута. Вот образец. Есть домашний компонент, который является родительским. И у него есть подкомпонент. Я просто хочу остановить функцию интервала, когда изменения маршрута в подкомпоненте смонтированы
import Home from "./components/Home.vue";
import Another from "./components/Another.vue";
const routes = [
{ path: '', component: Home },
{ path: '/another', component: Another }
];
const router = new VueRouter({
routes
});
const app = new Vue({
router
}).$mount('#app');
И это домашний компонент. Home.vue
<template>
<sub-component></sub-component>
</template>
<script type="text/babel">
import SubComponent from "./components/Subcomponent.vue";
export default {
components:{
'sub-component':SubComponent
}
}
</script>
И это подкомпонент. Subcomponent.vue
<template>
<div> Sub component will run a interval </div>
</template>
<script type="text/babel">
import SubComponent from "./components/Subcomponent.vue";
export default {
components:{
'sub-component':SubComponent
},
mounted:function(){
setInterval(function(){
console.log("I should cancel when route changed");
},1000)
}
}
</script>
Я пробовал метод beforeRouteLeave, но он останавливает только методы Home.vue.
1 ответ
Поскольку вы используете подкомпонент (внутри компонента маршрута), вы не сможете использовать beforeRouteLeave
непосредственно.
Ваш подкомпонент является дочерним компонентом маршрута. Поэтому вам нужно вызвать метод выхода дочернего компонента из компонента маршрута, используя ссылки на дочерний компонент, как описано на странице руководства ниже:
https://vuejs.org/v2/guide/components.html
Вы можете создать ссылку на свой подкомпонент следующим образом:
<sub-component ref="mySubComponent"></sub-component>
И теперь в вашем компоненте маршрута вы можете сделать следующее:
beforeRouteLeave: function(to, from, next) {
// Indicate to the SubComponent that we are leaving the route
this.$refs.mySubComponent.prepareToExit();
// Make sure to always call the next function, otherwise the hook will never be resolved
// Ref: https://router.vuejs.org/en/advanced/navigation-guards.html
next();
}
Примечание. Ваш компонент маршрута вызывает метод в дочернем подкомпоненте, который называется prepareToExit()
в этом примере вы можете выполнить очистку следующим образом:
methods: {
prepareToExit: function() {
console.log("Preparing to exit sub component, stopping 'twoSecondsTimerEvents'")
clearInterval(this.twoSecondsTimerEvents)
}
}
Вот рабочий пример: https://jsfiddle.net/mani04/crwuxez3/ (все подробности вошли в консоль)
Обратите внимание: в этом примере используются Vue 2.1.10 и Vue-Router 2.2.0 (последние версии на сегодняшний день). В предыдущих версиях были некоторые проблемы, связанные с функциями Навигационной охраны, которые теперь полностью решены.
РЕДАКТИРОВАТЬ: Альтернативный метод
После публикации вышеуказанного решения я понял, что существует более простой способ сделать это. Ваш подкомпонент может не получить специфичные для маршрута обратные вызовы, такие как beforeRouteLeave
, но это все еще компонент Vue, который следует жизненному циклу компонента.
Итак, основываясь на диаграмме жизненного цикла компонента, вы будете иметь beforeDestroy
обратный вызов в подкомпоненте, который можно использовать для очистки таймера.
Вот как вы можете это сделать:
const SubComponent = Vue.component('sub-component', {
template: `...`,
data: function() {...},
mounted: function() {...},
// 'prepareToExit' method not required here
// And also there is no need to handle 'beforeRouteLeave' in parent
beforeDestroy: function() {
console.log("Stopping the interval timer")
clearInterval(this.twoSecondsTimerEvents)
}
});
Преимущества:
- Гораздо проще, чем предыдущий подход.
- Нет необходимости обрабатывать ссылки на дочерний компонент в родительском компоненте.
- Нет необходимости запускать метод очистки из родительского компонента.
Нет никаких недостатков, но этот триггер не совсем привязан к изменению маршрута, если вы хотите выполнить какие-либо другие действия, основанные на маршруте назначения. Вы также можете использовать это, если вам это нравится больше.