2017-02-04 49 views
3

私は簡単な質問があります。ルートが変更されたときにサブコンポーネントをキャンセルしたいだけです。ここにサンプルがあります。親であるホームコンポーネントがあります。それにはサブコンポーネントがあります。私は、サブコンポーネントの経路変更がマウントされたときにインターバル機能を停止したいだけですVueルータ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メソッドのみを停止しました。

答えて

4

ルートコンポーネント内のサブコンポーネントを使用しているため、beforeRouteLeaveを直接使用することはできません。

あなたのサブコンポーネントは、子コンポーネントのルートです。下記の案内ページで説明したようにそのため、あなたは子コンポーネント参考文献を使用して、ルート要素から子コンポーネントのexitメソッドをトリガーする必要があります。

https://vuejs.org/v2/guide/components.html#Child-Component-Refs

次のようにあなたのサブコンポーネントへの参照を作成することができます:

<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(本日現在の最新バージョン)を使用しています。以前のバージョンでは、Navigation Guards関数のいくつかの問題がありましたが、これは完全に解決されました。

EDIT:代替方法

上記の溶液を掲示した後、私はそれを行うための簡単な方法があることに気づきました。あなたのサブコンポーネントは、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) 
    } 
}); 

利点:

  1. 以前のアプローチよりもはるかに簡単にここで

    は、あなたがそれを行うことができる方法です。

  2. 親コンポーネント内の子コンポーネント参照を処理する必要はありません。
  3. 親コンポーネントからクリーンアップメソッドをトリガーする必要はありません。

宛先のルートに基づいて他のアクションを実行したい場合は、このトリガーはルートの変更には正確に結びついていません。これがより好きなら、これを使うこともできます。

+0

ありがとうございました。それは私の問題を解決する。しかし、私はbeforeRouteLeaveがすべてのサブコンポーネントプロセスを殺すべきだと思います。そうですか? –

+0

Vueルータは、Vue固有の項目のみをクリーンアップします。 'setInterval'はjavascript仕様の一部です。これは手動で、またはページから遠ざかるまで(スペックに従って)永遠に実行されます。 – Mani

+0

私はちょうど解決策がはるかに簡単になることを認識し、私は私の答えに代替方法を追加しました。元の方法は依然として有効です。要件に基づいてこれらの方法のいずれかを選択することができます。 – Mani

関連する問題