Состояние Vuex в Vue. js вычисляется возвращаемым до инициализации - PullRequest
0 голосов
/ 08 апреля 2020

Я пытаюсь заполнить данные диаграммы, но сначала мне нужно получить данные для ее заполнения. Эти данные находятся в моем состоянии vuex, которое использует запрос API для получения данных. Но когда я возвращаю это состояние, это пустой массив. Как я могу убедиться, что данные заданы до того, как я их верну?

мое состояние vuex;

import axios from 'axios';

const state = {
    boardPosts: [],
    boardColumnData: []
};

const actions = {
    getAllBoardPostData: ({commit}) => {
        function getBoardColumns() {
            return axios.get('http://localhost:5000/api/summary-board/columns');
        }

        function getBoardPosts() {
            return axios.get('http://localhost:5000/api/summary-board/posts');
        }

        axios.all([getBoardColumns(), getBoardPosts()])
            .then(axios.spread((columnData, postData) => {
                let rawPosts = postData.data;
                let columns = columnData.data;
                let posts = Array.from({length: columns.length}, ()=> []);

                rawPosts.forEach((post) => {
                    // If column index matches post column index value
                    if(posts[post.column_index]){
                        posts[post.column_index].push(post);
                    }
                });

                columns.forEach((column, index) => {
                    let columnValue = 0;

                    posts[index].forEach((post) => {
                        columnValue += post.annual_value;
                    });

                    column.column_value = columnValue;
                });

                commit('setBoardColumns', columns);
                commit('setBoardPosts', posts);
            }))
            .catch(error => console.log(error));
    }
};

const mutations = {
    setBoardPosts: (state, payload) => {
        state.boardPosts = payload;
    },
    setBoardColumns: (state, payload) => {
        state.boardColumnData = payload;
    }
};

export default {
    state,
    actions,
    mutations
};

в моем файле vue;

export default {
    name: "Doughnut",
    computed: {
        boardColumns() {
            return this.$store.state.Dashboard.boardColumnData;
        }
    },
    created() {
        this.populate();
    },
    methods: {
        populate() {
            console.log(this.boardColumns) 
        }
    }
};

Ответы [ 3 ]

1 голос
/ 08 апреля 2020

Видя свою проблему, вы можете настроить наблюдатель на получателе магазина Vuex и выполнить свою задачу, как только получите значение.

Определите получатель как

getters: {
    getBoardData: state => state.boardColumnData
}

и сопоставьте получатель и создайте наблюдателя как

computed: {
    ...mapGetters(['getBoardData'])
},
watch: {
    getBoardData: {
        immediate: true,
        handler(to, from) {
            if(to) {
                //handle your changes
                this.populate()
            }
        }
    }
}

Если вы отправили действие в том же компоненте, так как действия асинхронные, вы могли бы приковать обратный вызов и вызвать populate() по завершении.

0 голосов
/ 08 апреля 2020

Это нормальное поведение, которое компонент будет отображать до Vuex store. Когда вычисляемая секция проверит, данные не будут инициализированы в store.

. Это может произойти, если вы используете запрос XHR для получения данных store.

Решением является использование условия v-if, когда используется свойство computed. В вашем случае вы можете проверить

v-if = "boardColumns.length>0"
0 голосов
/ 08 апреля 2020

Вы, кажется, забыли фактически отправить действие для получения данных. Попробуйте это в созданном хуке:

created() {
  this.$store.dispatch('Dashboard', 'getAllBoardPostData');
  this.populate();
}

РЕДАКТИРОВАТЬ:

Отправка действия в другой компонент в порядке. В этом случае созданный хук может быть слишком ранним в жизненном цикле, чтобы ждать получения данных (поскольку этот компонент не знает о том, кто выполняет диспетчеризацию), и он запускается только один раз. Вы можете добавить наблюдатель, чтобы дождаться изменения вычисленного свойства и вызвать побочный эффект (метод populate).

watch: { 
  boardColumns() { 
    this.populate() 
  } 
}

Или, если данные необходимы для визуализации компонента, вы можете использовать эти данные для определения v-if в родительском компоненте, как предложено @Estus Flask. В зависимости от того, как ваш компонент структурирован с точки зрения повторного использования и жесткой связи с магазином, вы можете даже передать его в качестве реквизита в этой точке.

// Parent component.vue

<template>
  <Doughnut 
    v-if="boardColumns && boardColumns.length"
    :boardColumns="boardColumns"
  />
</template>

<script>
import Doughnut from './Doughnut.vue'

export default {
  components: {
    Doughnut,
  },
  computed: {
    boardColumns() {
      return this.$store.state.Dashboard.boardColumns
    }
  }
}
</script>

// Doughnut.vue

<template>
  <div>
    {{ boardColumns }}
  </div>
</template>

<script>
  export default {
    name: "Doughnut",
    props: {
      boardColumns: {
        type: Object,
        required: true,
      }
    },
    created() {
      this.populate();
    },
    methods: {
      populate() {
        console.log(this.boardColumns) 
      }
    }
};
</script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...