2017-07-29 14 views
1

私が取り組んでいるウェブサイトでは、要件を達成するためにイベントエミッタを使用しなければなりませんでした。 fiddleをご覧ください。新しいメッセージを追加するときはうまくいくはずです。しかし、問題は、route1またはroute2をクリックしてParentビューに戻ると開始されます。次に、新しいメッセージを追加しようとします。 2回か3回表示されます(すべてのルートを訪れて戻る場合)。私は何が起こっているかについて完全にはわかっていない。この問題を解決するための提案は素晴らしいでしょう。

PS:コンポーネントは、親コンポーネントの直接の子ではありませんので、私のプロジェクトで、私は、ユーザー$rootに持っているので、$parentの代わり$rootを使用することをお勧めしないでください。

これは例です。

const Parent = { 
 
\t template: ` 
 
    <div> 
 
    <child-component></child-component> 
 
    <p v-for="msg in allMessages">{{msg}}</p> 
 
    </div> 
 
    `, 
 
    computed: { 
 
    allMessages: function() { 
 
     return this.$root.$store.state.storedMessages 
 
    } 
 
    }, 
 
    mounted(){ 
 
    this.$root.$on('NewMessage', function(data){ 
 
    \t this.$store.dispatch('newMessage', data) 
 
    }) 
 
    } 
 
} 
 
Vue.component('navs', { 
 
\t template: ` 
 
    <div> 
 
    <div class="left-nav-menu"> 
 

 
      <router-link to="/">Parent</router-link> 
 

 
      <router-link to="/route1">route1</router-link> 
 

 
      <router-link to="/route2">route2</router-link> 
 

 
    </div> 
 
    </div> 
 
` 
 
}) 
 

 
Vue.component('child-component', { 
 
    template: ` 
 
    \t <form id="messageForm" @submit.prevent="sendMessage"> 
 
     <input type="text" v-model="message"> 
 
     <button type="submit" >Send Message</button> 
 
    </form> 
 
    `, 
 
    data() { 
 
    return { 
 
     message: '' 
 
    } 
 
    }, 
 
    computed: { 
 
    \t allMessages: function() { 
 
     return this.$root.$store.state.storedMessages 
 
    } 
 
    }, 
 
    methods: { 
 
    sendMessage: function() { 
 
     this.$root.$emit('NewMessage', this.message) 
 
    } 
 
    } 
 
}) 
 

 
const route1 = { 
 
\t template: `<p>Route1</p>` 
 
} 
 
const route2 = { 
 
\t template: `<p>Route2</p>` 
 
} 
 

 
const store = new Vuex.Store({ 
 
\t state: { 
 
    \t storedMessages: [] 
 
    }, 
 
    mutations: { 
 
    \t newMessage(state, data) { 
 
      state.storedMessages.push(data) 
 
     } 
 
    }, 
 
    actions: { 
 
     newMessage({commit}, payload) { 
 
     
 
      commit('newMessage', payload) 
 
     } 
 
    } 
 
}) 
 
const router = new VueRouter({ 
 
\t routes: [ 
 
    \t { name: 'parent', path: '/', component: Parent }, 
 
    { name: 'route1', path: '/route1', component: route1 }, 
 
     { name: 'route2', path: '/route2', component: route2 } 
 
    ] 
 
}) 
 
new Vue({ 
 
\t el: '#app', 
 
    store, 
 
    router 
 
})
* { 
 
    box-sizing: border-box; 
 
} 
 

 
.listing { 
 
    list-style-type: none; 
 
    overflow: hidden; 
 
    padding: 0; 
 
    li { 
 
    float: left; 
 
    width: 175px; 
 
    padding: 10px; 
 
    text-align: center; 
 
    border: 1px #ddd solid; 
 
    background: white; 
 
    margin: 5px; 
 
    cursor: pointer; 
 
    img { 
 
     width: 100%; 
 
     margin-bottom: 7px; 
 
    } 
 
    &:hover { 
 
     background: #eee; 
 
    } 
 
    } 
 
} 
 

 
.item-view { 
 
    text-align: center; 
 
} 
 

 
.item { 
 
    background: white; 
 
    padding: 10px; 
 
} 
 

 
a { 
 
    font-size: 16px; 
 
    display: inline-block; 
 
    padding: 10px; 
 
    border: 1px #ddd solid; 
 
    background: white; 
 
    color: black; 
 
    margin: 10px; 
 
    &.back-listing { 
 
    position: absolute; 
 
    left: 0; 
 
    top: 0; 
 
    } 
 
}
<script src="https://unpkg.com/vue/dist/vue.js"></script> 
 
<script src="https://unpkg.com/vuex/dist/vuex.js"></script> 
 
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> 
 
<div id="app"> 
 
    <navs></navs> 
 
    <router-view></router-view> 
 
</div>

答えて

3

あなたが継続的にmountedにメッセージハンドラを追加しているので、これが起こっています。それらを削除する必要があります。

const Parent = { 
    template: ` 
    <div> 
    <child-component></child-component> 
    <p v-for="msg in allMessages">{{msg}}</p> 
    </div> 
    `, 
    computed: { 
    allMessages: function() { 
     return this.$root.$store.state.storedMessages 
    } 
    }, 
    methods:{ 
    sendMessage(data){ 
     this.$store.dispatch('newMessage', data) 
    } 
    }, 
    mounted(){ 
    this.$root.$on('NewMessage', this.sendMessage) 
    }, 
    beforeDestroy(){ 
    this.$root.$off('NewMessage', this.sendMessage) 
    } 
} 

コードを更新しました。

const Parent = { 
 
\t template: ` 
 
    <div> 
 
    <child-component></child-component> 
 
    <p v-for="msg in allMessages">{{msg}}</p> 
 
    </div> 
 
    `, 
 
    computed: { 
 
    allMessages: function() { 
 
     return this.$root.$store.state.storedMessages 
 
    } 
 
    }, 
 
    methods:{ 
 
    \t sendMessage(data){ 
 
     this.$store.dispatch('newMessage', data) 
 
    } 
 
    }, 
 
    mounted(){ 
 
    this.$root.$on('NewMessage', this.sendMessage) 
 
    }, 
 
    beforeDestroy(){ 
 
    this.$root.$off('NewMessage', this.sendMessage) 
 
    } 
 
} 
 

 
Vue.component('navs', { 
 
\t template: ` 
 
    <div> 
 
    <div class="left-nav-menu"> 
 

 
      <router-link to="/">Parent</router-link> 
 

 
      <router-link to="/route1">route1</router-link> 
 

 
      <router-link to="/route2">route2</router-link> 
 

 
    </div> 
 
    </div> 
 
` 
 
}) 
 

 
Vue.component('child-component', { 
 
    template: ` 
 
    \t <form id="messageForm" @submit.prevent="sendMessage"> 
 
     <input type="text" v-model="message"> 
 
     <button type="submit" >Send Message</button> 
 
    </form> 
 
    `, 
 
    data() { 
 
    return { 
 
     message: '' 
 
    } 
 
    }, 
 
    computed: { 
 
    \t allMessages: function() { 
 
     return this.$root.$store.state.storedMessages 
 
    } 
 
    }, 
 
    methods: { 
 
    sendMessage: function() { 
 
     this.$root.$emit('NewMessage', this.message) 
 
    } 
 
    } 
 
}) 
 

 
const route1 = { 
 
\t template: `<p>Route1</p>` 
 
} 
 
const route2 = { 
 
\t template: `<p>Route2</p>` 
 
} 
 

 
const store = new Vuex.Store({ 
 
\t state: { 
 
    \t storedMessages: [] 
 
    }, 
 
    mutations: { 
 
    \t newMessage(state, data) { 
 
      state.storedMessages.push(data) 
 
     } 
 
    }, 
 
    actions: { 
 
     newMessage({commit}, payload) { 
 
     
 
      commit('newMessage', payload) 
 
     } 
 
    } 
 
}) 
 
const router = new VueRouter({ 
 
\t routes: [ 
 
    \t { name: 'parent', path: '/', component: Parent }, 
 
    { name: 'route1', path: '/route1', component: route1 }, 
 
     { name: 'route2', path: '/route2', component: route2 } 
 
    ] 
 
}) 
 
new Vue({ 
 
\t el: '#app', 
 
    store, 
 
    router 
 
})
* { 
 
    box-sizing: border-box; 
 
} 
 

 
.listing { 
 
    list-style-type: none; 
 
    overflow: hidden; 
 
    padding: 0; 
 
    li { 
 
    float: left; 
 
    width: 175px; 
 
    padding: 10px; 
 
    text-align: center; 
 
    border: 1px #ddd solid; 
 
    background: white; 
 
    margin: 5px; 
 
    cursor: pointer; 
 
    img { 
 
     width: 100%; 
 
     margin-bottom: 7px; 
 
    } 
 
    &:hover { 
 
     background: #eee; 
 
    } 
 
    } 
 
} 
 

 
.item-view { 
 
    text-align: center; 
 
} 
 

 
.item { 
 
    background: white; 
 
    padding: 10px; 
 
} 
 

 
a { 
 
    font-size: 16px; 
 
    display: inline-block; 
 
    padding: 10px; 
 
    border: 1px #ddd solid; 
 
    background: white; 
 
    color: black; 
 
    margin: 10px; 
 
    &.back-listing { 
 
    position: absolute; 
 
    left: 0; 
 
    top: 0; 
 
    } 
 
}
<script src="https://unpkg.com/vue/dist/vue.js"></script> 
 
<script src="https://unpkg.com/vuex/dist/vuex.js"></script> 
 
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> 
 
<div id="app"> 
 
    <navs></navs> 
 
    <router-view></router-view> 
 
</div>

+0

はいありがとう。私は 'this。$ root。$ off'を追加することを考えていました。 @Bertをいつものように素早く返信してくれてありがとう – Pradeepb

+0

ちょっと好奇心が強い、そのような細かいレベルの詳細を知る場所は? )それはVueJSのドキュメントまたはちょうど経験に記載されています;) – Pradeepb

+1

@Pradeepb私はこれについてのドキュメントにあなたを指摘できませんでした、それはあなたが一般的に覚えておく必要があるものです。あなたが*イベントハンドラを追加するときはいつでも、*削除する必要があるときに考慮する必要があります。ほとんどの場合、Vueは(あなたが 'v-on'などでハンドラを追加したときのように)これらの詳細を隠します。 – Bert