如何在vuex中从API中获取数据

How to fetch data from API in vuex

我想使用 vuex 来存储从服务器获取的一些数据,我的 SPA Vue 应用程序需要在不同的页面中使用这些数据,这样可以避免每次用户更改时都发出新的 ajax 请求产品页面(这是一个无头电子商务)。

我的问题很简单,如何将获取的数据推送到我的商店中定义的数组中?我将如何获取组件中的数据?我正在写代码,但不确定我是否做得好。

import { createStore } from 'vuex'
import axios from 'axios'

export default createStore({
  state: {
    products: []
  },
  mutations: {
    updateProductsData(state, products){
      // not sure how to proceed here
    }
  },
  actions: {
    fetchProducts(){
      const baseURL = 'https://www.example.com/app/index.php/wp-json/shop/v1/products';
      let productsData = [];
      axios.get(baseURL).then( response => {
        response.data.forEach( el => {    
          console.log(el);
          let details = {
            id: el.id,
            slug: el.slug,
            name: el.name,
            price: el.price,
            description: el.description,
            short_description: el.short_description
          }
          productsData.push(details);
        });
        store.commit('updateProductsData', productsData);
      }).catch( e => console.log(e) );
    }
  }
})

在我需要加载数据的组件中,我有这段代码


export default {
  name: 'Home',
  data(){
    return {
      loaded: false,
      offers: [],      
    }
  },
  created(){

  }, 
  mounted(){
    this.$store.dispatch('fetchProducts').then( res => this.offers.push(res) )   
  },
}

将您的商店操作更新为 return 产品数据数组。

fetchProducts() {
  const baseURL = "https://www.example.com/app/index.php/wp-json/shop/v1/products";
  const productsData = [];

  axios
    .get(baseURL)
    .then(response => {
      response.data.forEach(el => {
        console.log(el);

        const details = {
          id: el.id,
          slug: el.slug,
          name: el.name,
          price: el.price,
          description: el.description,
          short_description: el.short_description
        };

        productsData.push(details);
      });
    })
    .catch(e => {
      console.log(e);
    });

  return productsData;
}

现在,当您从您的组件发送操作时,我们会发回结果。

更好的方式

更好的方法是 return Axios 调用本身,这是一个 Promise,您可以 await 在您的组件中。

或者,您可以将 Axios 调用包装在您自己的 Promise 中,并仅使用数据、处理错误和组件中的对象来解决它,以便更好地向用户反馈,如下所示:

fetchProducts() {
  const baseURL = "https://www.example.com/app/index.php/wp-json/shop/v1/products";

  return new Promise((resolve, reject) => {
    axios
      .get(baseURL)
      .then(response => {
        resolve(response.data);
      })
      .catch(e => {
        reject(e);
      });
  });
}

有道

要正确使用商店,您应该像这样实现 VueX 操作:

fetchProducts({ commit }) {
  const baseURL = "https://www.example.com/app/index.php/wp-json/shop/v1/products";

  axios
    .get(baseURL)
    .then(response => {
      commit("setProductData", res.data);
    })
    .catch(e => {
      console.log(e); 
    });
  });
}

添加以下突变:

setProductData(state, productData) {
  state.products = productData.map(product => {
    return {
      id: product.id,
      slug: product.slug,
      name: product.name,
      price: product.price,
      description: product.description,
      short_description: product.short_description
    };
  });
}

将您的组件更新为:

export default {
  name: "Home",
  data() {
    return {
      loaded: false,
      offers: []
    };
  },
  computed: {
    products() {
      return this.$store.state.products;
    }
  },
  mounted() {
    this.$store.dispatch("fetchProducts");
  }
};

要按 ID 获取,请添加计算的 属性,例如:

findProductById(id) {
  return this.products.find(product => product.id === id);
}

在您的 updateProductsData 突变中使用 state.products = [...products] 将您加载的产品添加到您的状态

查看 https://www.vuemastery.com/courses/vuex-fundamentals/vuex4-intro-to-vuex 了解 Vuex 的简短介绍

您可以参考 Vuex 的文档关于动作和突变的使用 https://vuex.vuejs.org/guide/actions.html 。很详细...

正如 Vuex 所建议的那样,您应该将异步操作放在操作中(例如在您的示例中从服务器获取数据)。然后你应该提交一个“突变”来使用获取的数据来设置你的状态,就像下面给出的代码

import { createStore } from 'vuex'
import axios from 'axios'

export default createStore({
  state: {
    products: []
  },
  mutations: {
    updateProductsData(state, products){
      // here set your state
      state.products = products
    }
  },
  actions: {
    fetchProducts({commit}){
      const baseURL = 'https://www.example.com/app/index.php/wp-json/shop/v1/products';
      let productsData = [];
      axios.get(baseURL).then( response => {
        response.data.forEach( el => {    
          console.log(el);
          let details = {
            id: el.id,
            slug: el.slug,
            name: el.name,
            price: el.price,
            description: el.description,
            short_description: el.short_description
          }
          productsData.push(details);
        });
        store.commit('updateProductsData', productsData);
      }).catch( e => console.log(e) );
    }
  }
})

如果你想在你的组件中使用状态,你可以把它放在计算属性中。

export default {
  name: 'Home',
  data(){
    return {
      loaded: false,
    }
  },
  computed:{
    // map this.offers to store.state.products
    offers(){
      return this.$store.state.products
    }
  },
  created(){

  }, 
  mounted(){
    // dispatch 'fetchProducts' to fetch data
    this.$store.dispatch('fetchProducts')
  },
}