Vue Router beforeRouteLeave 不会停止子组件
Vue Router beforeRouteLeave doesn't stop subcomponents
我有一个简单的问题。我只想在路线更改时取消子组件。这是一个示例。有一个家庭组件,它是父组件。它有一个子组件。我只想在子组件 mounted
中的路由发生变化时停止 interval 函数
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 个方法。
由于您正在使用 sub-component(在路由组件内),您将无法直接使用 beforeRouteLeave
。
您的 sub-component 是路线的 子组件 。因此,您需要使用 Child Component Refs 从路由组件触发子组件的退出方法,如下面的指南页面所述:
https://vuejs.org/v2/guide/components.html#Child-Component-Refs
您可以创建对您的 sub-component 的引用,如下所示:
<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();
}
注意:在本例中,您的路由组件调用子 sub-component 中的方法 prepareToExit()
,您可以在其中执行 clean-up,如下所示:
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(截至今天的最新版本)。之前的版本有一些问题,围绕Navigation Guards个函数,现在已经完全解决了。
编辑:替代方法
在发布了上面的解决方案后,我意识到还有更简单的方法可以做到。您的 sub-component 可能不会像 beforeRouteLeave
那样获得特定于路由的回调,但它仍然是一个遵循组件生命周期的 Vue 组件。
因此,基于 component lifecycle diagram,您将在子组件中有 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)
}
});
优点:
- 比以前的方法简单得多。
- 无需处理父组件中的任何子组件引用。
- 无需从父组件触发清理方法。
没有缺点,但是这个触发器并不完全依赖于路由更改,以防您想根据目标路由执行任何其他操作。如果你更喜欢这个,你也可以使用它。
我有一个简单的问题。我只想在路线更改时取消子组件。这是一个示例。有一个家庭组件,它是父组件。它有一个子组件。我只想在子组件 mounted
中的路由发生变化时停止 interval 函数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 个方法。
由于您正在使用 sub-component(在路由组件内),您将无法直接使用 beforeRouteLeave
。
您的 sub-component 是路线的 子组件 。因此,您需要使用 Child Component Refs 从路由组件触发子组件的退出方法,如下面的指南页面所述:
https://vuejs.org/v2/guide/components.html#Child-Component-Refs
您可以创建对您的 sub-component 的引用,如下所示:
<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();
}
注意:在本例中,您的路由组件调用子 sub-component 中的方法 prepareToExit()
,您可以在其中执行 clean-up,如下所示:
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(截至今天的最新版本)。之前的版本有一些问题,围绕Navigation Guards个函数,现在已经完全解决了。
编辑:替代方法
在发布了上面的解决方案后,我意识到还有更简单的方法可以做到。您的 sub-component 可能不会像 beforeRouteLeave
那样获得特定于路由的回调,但它仍然是一个遵循组件生命周期的 Vue 组件。
因此,基于 component lifecycle diagram,您将在子组件中有 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)
}
});
优点:
- 比以前的方法简单得多。
- 无需处理父组件中的任何子组件引用。
- 无需从父组件触发清理方法。
没有缺点,但是这个触发器并不完全依赖于路由更改,以防您想根据目标路由执行任何其他操作。如果你更喜欢这个,你也可以使用它。