【问题标题】:How do I load Vuex data before a component is rendered?如何在渲染组件之前加载 Vuex 数据?
【发布时间】:2021-04-19 02:59:22
【问题描述】:

我在 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 中创建的钩子中调度操作,但无济于事。

【问题讨论】:

  • 如果你想在第一次渲染之前进行 AJAX 调用 - 你应该使用 beforeMount 钩子。如果您还想捕获所有后续重新渲染,那么您还应该使用 beforeUpdate 钩子。
  • 两个钩子都试过了,都没有得到数据。
  • 当 AJAX 调用完成时你会得到数据——但那时 Vue 可能已经渲染了组件,所以数据到达会触发重新渲染。
  • 我认为你的应用程序没有重新渲染的问题是你在你的getter中检索整个state......我知道在较新版本的Vue和Vuex中,反应式更好,它可以识别数组或子属性的变化。但是我建议您做的第一件事是:在您的状态中创建一个名为 weather 的属性,并在您的突变中,在检索数据时为该属性设置一个全新的对象,然后在您的 getter 中您只返回 @ 987654326@.
  • 感谢您的建议。但这很可能不是因为返回整个州。我什至尝试在 getter 和突变中只返回一个属性。此外,问题不在于重新渲染,数据甚至没有在第一页加载时加载到计算属性中。奇怪的是,我可以在控制台中看到该操作已调度,但由于某种原因,计算的属性没有接收到数据。但是当页面重新加载时,他们就会得到数据。

标签: vue.js vuejs2 vuex


【解决方案1】:

使用 mapActions 似乎可以做到。

所以在组件中我们将拥有

<template>
  <!-- <div>
  <v-card> {{ weatherGetter }} </v-card>
  </div>
</template>
    
<script>    
import { mapActions } from 'vuex';


export default {
  data() {
    return {
    };
  },
methods: {
    ...mapActions({
      getWeather: 'getWeather',
    }),
},
  computed: {
    weatherGetter() {
      return this.$store.getters('weatherGetter');
    },
  },
  mounted() {
    this.getWeather();
  };
</script>

【讨论】:

    【解决方案2】:

    这能解决您的问题吗?

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

    【讨论】:

    • 你的getter有你想要的值吗?
    猜你喜欢
    • 2019-01-19
    • 2016-06-09
    • 1970-01-01
    • 2018-11-29
    • 2019-08-09
    • 2017-01-06
    • 2021-12-09
    • 1970-01-01
    相关资源
    最近更新 更多