如何在vue

时间:2017-07-01 20:17:05

标签: vue.js vuex

我有一个包含数组game的vuex-store players

每个player都有idnamescore

我现在有一个组件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 个答案:

答案 0 :(得分:1)

如果没有看到你如何使用记分板组件,很难说它为什么不更新。

无论如何,如果您要删除scoreBoard组件中的属性播放器并使用带有mapState或mapGetters的Vuex状态播放器,它会在您更改播放器数据后自动更新您的电路板。

我在下面创建演示时检测到的另一点是你按分数排序,但我认为它应该是积分。因为您所在的州没有得分属性,或者得分计算不在您的代码段中。

请查看下面的演示或fiddle

我认为你的装载分拣是可以的。我刚刚推翻了结果以获得最高分。

在您的addPoints变异方法中,我更改为速记+=因为我认为更容易阅读 - 您的版本在这里也可以。

mapState或mapMutations演示中的注释代码与映射器的作用相同,并留在那里以了解映射器正在做什么。

&#13;
&#13;
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: `
  	<div>
    	Name: {{player.name}}<br/>
      Score: {{player.points}}
      <pre>Debug:
{{player}}
      </pre>
    </div>
  `
};

const scoreBoard = {
  //props: ['players'],
  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>
  `,
  data() {
    return {}
  },
  components: {
    ScoreBoardEntry
  },
  computed: {
    ...Vuex.mapState({
    	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
    	console.log(this.$store.state.game.players);
    	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() {
  	return {
    	testData: {
      	id: 2,
        points: 10
      }
    };
  },
  components: {
    scoreBoard
  },
  methods: {
  	/*addPoints(payload) {
    	this.$store.commit('game/addPoints', payload);
    }*/
  	...Vuex.mapMutations({
    	addPoints: 'game/addPoints'
    })
  }
});
&#13;
<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>
&#13;
&#13;
&#13;