2017-07-01 83 views
1

一個selfupdating排序我有一個vuex店game其中包含一個數組players如何實現VUE

每個player有一個id,namescore

我現在有一個組件scoreboard應該由他們的得分列出所有球員。

要排序玩家,我向我的組件添加了一個計算屬性。

當我現在在應用程序某處更新玩家分數時,我的計算屬性不會被觸發。我知道它沒有被觸發,因爲數組本身沒有改變。我需要調用push/pop/shift /改變數組的任何東西。

解決此問題的常用方法是什麼?當我更新一些屬性時,是否也應該改變數組?由於呈現player.points已經成功更新的組件,這看起來很髒。

有沒有辦法來添加更多聽衆的計算性能?

我的組件:

<template> 
    <div class="scoreboard"> 
    <strong>Scoreboard</strong> 
    <div class="scores"> 
     <score-board-entry v-for="player in sortedPlayers" :key="player.id" :player="player"></score-board-entry> 
    </div> 
    </div> 
</template> 

<script> 
import _ from 'lodash' 
import ScoreBoardEntry from './ScoreBoardEntry.vue' 

export default { 
    props: ['players'], 
    data() { 
    return { } 
    }, 
    components: { ScoreBoardEntry }, 
    computed: { 
    sortedPlayers() { 
     return _.sortBy(this.players, 'score') 
    } 
    } 
} 
</script> 

<style scoped> 
</style> 

我的店:

const initialState: state = { 
    id: '', 
    players: [] 
} 

const game = { 
    namespaced: true, 
    state: initialState, 
    mutations: { 

    addPoints (state: state, payload: addPointsPayload) { 
     const player = state.players.find((p) => p.id === payload.id)  
     player.points = player.points + payload.points 
    } 
... 

回答

1

隨着淘汰看到你是如何使用你的分數板組件,但是很難說爲什麼它沒有更新。無論如何,如果您要刪除scoreBoard組件中的屬性玩家,並使用帶有mapState或mapGetters的Vuex狀態玩家,只要您更改玩家數據,它就會自動更新您的棋盤。

我創建下面的演示中已經檢測到的另一點是,你按分數排序,但我認爲它應該是點。因爲您的狀態中沒有得分屬性,或者得分計算不在您的片段中。

請看看下面或在此fiddle演示。

而我認爲你的loadash排序是確定的。我剛剛扭轉了結果,以第一的最高分。

在你addPoints突變方法我改速記+=,因爲我認爲這是更容易閱讀 - 你的版本也確定在這裏。

在mapState或mapMutations演示註釋代碼都在做一樣的映射器並離開那裏瞭解什麼映射器在做什麼。

const initialState = { 
 
    id: '', 
 
    players: [{ 
 
    id: 0, 
 
    name: 'first', 
 
    points: 20 
 
    }, { 
 
    id: 1, 
 
    name: 'second', 
 
    points: 10 
 
    }, { 
 
    id: 2, 
 
    name: 'third player', 
 
    points: 35 
 
    }] 
 
}; 
 

 
const game = { 
 
    namespaced: true, 
 
    state: initialState, 
 
    mutations: { 
 
    addPoints(state, payload) { 
 
     const player = state.players.find((p) => p.id === parseInt(payload.id)); 
 
     //console.log('addpoints', payload, player); 
 
     player.points += payload.points; 
 
    } 
 
    } 
 
}; 
 

 
const ScoreBoardEntry = { 
 
    props: ['player'], 
 
    template: ` 
 
    \t <div> 
 
    \t Name: {{player.name}}<br/> 
 
     Score: {{player.points}} 
 
     <pre>Debug: 
 
{{player}} 
 
     </pre> 
 
    </div> 
 
    ` 
 
}; 
 

 
const scoreBoard = { 
 
    //props: ['players'], 
 
    template: ` 
 
    \t <div class="scoreboard"> 
 
    <strong>Scoreboard</strong> 
 
    <div class="scores"> 
 
     <score-board-entry v-for="player in sortedPlayers" :key="player.id" :player="player"></score-board-entry> 
 
    </div> 
 
    </div> 
 
    `, 
 
    data() { 
 
    return {} 
 
    }, 
 
    components: { 
 
    ScoreBoardEntry 
 
    }, 
 
    computed: { 
 
    ...Vuex.mapState({ 
 
    \t players: (state) => state.game.players // info: mapping more complicated here because of module --> with-out module we could just use ...mapState(['players]); 
 
    }), 
 
    /*players() { // same as mapState 
 
    \t console.log(this.$store.state.game.players); 
 
    \t return this.$store.state.game.players; 
 
    },*/ 
 
    sortedPlayers() { 
 
     return _.sortBy(this.players, 'points').reverse(); //'score') 
 
    } 
 
    } 
 
}; 
 

 
Vue.use(Vuex); 
 

 
const store = new Vuex.Store({ 
 
    modules: { 
 
    game 
 
    } 
 
}); 
 

 
new Vue({ 
 
    el: '#app', 
 
    store, 
 
    data() { 
 
    \t return { 
 
    \t testData: { 
 
     \t id: 2, 
 
     points: 10 
 
     } 
 
    }; 
 
    }, 
 
    components: { 
 
    scoreBoard 
 
    }, 
 
    methods: { 
 
    \t /*addPoints(payload) { 
 
    \t this.$store.commit('game/addPoints', payload); 
 
    }*/ 
 
    \t ...Vuex.mapMutations({ 
 
    \t addPoints: 'game/addPoints' 
 
    }) 
 
    } 
 
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.3.1/vuex.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script> 
 
<div id="app"> 
 
    user id: <input v-model="testData.id"> 
 
    points: <input v-model="testData.points" type="number"> 
 
    <button @click="addPoints(testData)"> 
 
    
 
    Add points 
 
    </button> 
 
    <score-board></score-board> 
 
</div>

+0

謝謝!這真的只是我的財產被錯誤地命名。 (-‸ლ) – Gundon

+0

不客氣。那麼錯誤的名字在哪裏?傳遞給'scoreBoard'的'players'道具是不對的? – AWolf

+0

是的。當排序'分數'是錯誤的,'分數'應該在那裏。 – Gundon