2017-07-01 72 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