首页 > 解决方案 > 如何在渲染组件之前加载 Vuex 数据?

问题描述

我在 vuex 模块中调用天气 API。我想要完成的是使用组件中的计算属性获取数据。使用当前设置,除了我需要刷新/重新加载页面以更新 vuex 状态外,没有任何问题。我已经尝试调度在已安装的钩子中获取数据的操作,但这也不起作用,因此必须手动重新加载页面才能为计算的属性分配数据。这样做的正确方法是什么?

Vuex store.js

import Vue from 'vue';
import Vuex from 'vuex';
import {
  Auth
} from 'aws-amplify';
import axios from 'axios';

var AWS = require('aws-sdk');
var AWSCognito = require('amazon-cognito-identity-js');

Auth.currentUserInfo

var data = {
    UserPoolId: '******************',
    ClientId: '******************',
  },
  userPool = new AWSCognito.CognitoUserPool(data);

var cognitoUser = userPool.getCurrentUser();

AWS.config.region = '******************';

Vue.use(Vuex);

const weatherService = {
  state: () => ({
    error: null,
    currentTemp: '',
    minTemp: '',
    maxTemp: '',
    sunrise: '',
    sunset: '',
    pressure: '',
    humidity: '',
    wind: '',
    overcast: '',
    name: '',
    latitude: '',
    longitude: '',
  }),
  mutations: {
    SET_WEATHER_DATA(state, payload) {
      state.currentTemp = payload.main.temp;
      state.minTemp = payload.main.temp_min + '°C';
      state.maxTemp = payload.main.temp_max + '°C';
      state.pressure = payload.main.pressure + 'hPa';
      state.humidity = payload.main.humidity + '%';
      state.wind = payload.wind.speed + 'm/s';
      state.overcast = payload.weather[0].description;
      state.sunrise = new Date(payload.sys.sunrise * 1000)
        .toLocaleTimeString('en-GB')
        .slice(0, 5);
      state.sunset = new Date(payload.sys.sunset * 1000)
        .toLocaleTimeString('en-GB')
        .slice(0, 5);
      state.name = payload.name;
    },
  },
  actions: {
    getWeather({
      commit
    }) {
      try {
        if (cognitoUser != null) {
          cognitoUser.getSession(function(err, session) {
            if (err) {
              console.log(err);
              return;
            }
            AWS.config.credentials = new AWS.CognitoIdentityCredentials({
              IdentityPoolId: '******************',
              Logins: {
                // Change the key below according to the specific region your user pool is in.
                'cognito-idp.******************.amazonaws.com/******************': session
                  .getIdToken()
                  .getJwtToken(),
              },
            });

            AWS.config.credentials.get(function(err) {
              if (!err) {
                var id = AWS.config.credentials.identityId;
                // Instantiate aws sdk service objects now that the credentials have been updated
                var docClient = new AWS.DynamoDB.DocumentClient({
                  region: AWS.config.region,
                });
                var params = {
                  //
                };

                params.ProjectionExpression = "user_meta_data";

                docClient.query(params, function(err, data) {
                  if (err) console.error(err);
                  else {
                    console.log(data);
                    const lat = data.Items[0].user_meta_data.coordinates.latitude
                    const long = data.Items[0].user_meta_data.coordinates.longitude

                    axios
                      .get(
                        'https://api.openweathermap.org/data/2.5/weather?lat=' +
                        lat +
                        '&lon=' +
                        long +
                        '&units=metric&APPID=' +
                        process.env.VUE_APP_OPEN_WEATHER_API_KEY
                      )
                      .then((response) => {
                        commit('SET_WEATHER_DATA', response.data)
                        console.log("dispatched!")
                      })
                      .catch((error) => {
                        console.log(error);
                      });
                  }
                });
              }
            });
          });
        }
      } catch (e) {
        console.log(e);
        return;
      }

    }
  },

  getters: {
    weatherGetter(state) {
      return state
    },
  },

};


const store = new Vuex.Store({
  modules: {
    w: weatherService
  },
  state: {
    //
  },
  mutations: {
    //
  },

  actions: {
    //
  },

  getters: {
    //
  },

});

export default store;

Weather.vue 组件

<template>
  <!-- <div>
  <v-card> {{ weatherGetter }} </v-card>
  </div>
</template>
    
<script>    
export default {
  data() {
    return {
    };
  },
  computed: {
    weatherGetter() {
      return this.$store.getters('weatherGetter');
    },
  },
  mounted() {
    this.$store.dispatch('getWeather');
  };
</script>

我查看了其他类似的问题,他们似乎建议使用 beforeRouteEnter,我认为这在我的情况下并不理想。我还尝试在 main.js 中创建的钩子中调度操作,但无济于事。

标签: vue.jsvuejs2vuex

解决方案


这能解决您的问题吗?

<template>
  <div v-if="weatherGetter">
  <v-card> {{ weatherGetter }} </v-card>
  </div>
</template>

推荐阅读