【问题标题】:how to get data from API in vuex using axios?如何使用 axios 从 vuex 中的 API 获取数据?
【发布时间】:2018-07-05 10:16:40
【问题描述】:

我有来自 API laravel 的数据,这是我在 state.js 中的代码

import axios from 'axios'
import {apiPostGet} from '../api/api'
export default {
  data: axios({
    method: 'GET',
    url: apiPostGet('Kategori')
  }).then(
    response => {
      return response.data.kategori
    }
  ).catch(
    error => {
      return error.response
    }
  )
}

这是我在 gteeters.js 中的代码

export default {
  datas: state => {
    return state.data
  }
}

这是我在 index.js 中的代码

import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import getters from './getters'

Vue.use(Vuex)

export default new Vuex.Store({
   state,
   getters
})

【问题讨论】:

标签: vue.js vuex


【解决方案1】:

我会使用 AWolf 的解决方案,但是 loadData 方法中的错误处理略有改进

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
  function getUrlParams() {
    var url_params = new URLSearchParams();
    if (window.location.toString().indexOf("?") != -1) {
      var href_part = window.location.search.split('?')[1]
      href_part.replace(/([^=&]+)=([^&]*)/g,
        function(m, key, value) {
          var attr = decodeURIComponent(key)
          var val = decodeURIComponent(value)
          url_params.append(attr, val);
        });
    }
    // for(var pair of url_params.entries()) { consolas.log(pair[0]+ '->'+ pair[1]); }
    return url_params;
  }


  function getServerData(url, urlParams) {
    if (typeof url_params == "undefined") {
      urlParams = getUrlParams()
    }
    return axios.get(url, {
        params: urlParams
      })
      .then(response => {
        return response;
      })
      .catch(function(error) {
        console.error(error)
        return error.response;
      })
  }

  // Action !!!
  getServerData(url, url_params)
    .then(response => {
      if (response.status === 204) {
        var warningMsg = response.statusText
        console.warn(warningMsg)
        return
      } else if (response.status === 404 || response.status === 400) {
        var errorMsg = response.statusText // + ": "  + response.data.msg // this is my api
        console.error(errorMsg)
        return;
      } else {
        var data = response.data
        var dataType = (typeof data)
        if (dataType === 'undefined') {
          var msg = 'unexpected error occurred while fetching data !!!'
          // pass here to the ui change method the msg aka
          // showMyMsg ( msg , "error")
        } else {
          var items = data.dat // obs this is my api aka "dat" attribute - that is whatever happens to be your json key to get the data from
          // call here the ui building method
          // BuildList ( items )
        }
        return
      }
    })
</script>

【讨论】:

    【解决方案2】:

    Data钩子需要同步返回。您必须将加载添加到 createdmounted 并将属性添加到数据/状态,这样反应性才起作用。

    使用 Axios 加载数据需要通过操作触发,因为它是异步的。突变需要同步运行。我在created 中添加了初始加载。 (mounted 也可以。)

    我使用了 Vuex 助手 mapState 将状态属性映射到组件。使用 getter 也可以,但 mapState 更容易编写。

    请看下面的演示或fiddle

    同时取消注释小提琴中 Vuex 版本下方的代码并评论上面的应用程序,以了解 Axios 在没有 Vuex 的情况下如何工作,以便更好地理解。

    const URL = 'https://jsonplaceholder.typicode.com/posts';
    
    const store = new Vuex.Store({
      state: {
        posts: [],
        loading: true
      },
      actions: {
        loadData({
          commit
        }) {
          axios.get(URL).then((response) => {
            // console.log(response.data, this)
            commit('updatePosts', response.data)
            commit('changeLoadingState', false)
          })
        }
      },
      mutations: {
        updatePosts(state, posts) {
          state.posts = posts
        },
        changeLoadingState(state, loading) {
          state.loading = loading
        }
      }
    })
    
    new Vue({
      el: '#app',
      computed: Vuex.mapState(['posts', 'loading']),
      store,
      created() {
        //console.log(this.$store)
        this.$store.dispatch('loadData') // dispatch loading
      }
    })
    
    /*
    	//example with-out vuex
      
    new Vue({
    	el: '#app',
    	data() {
      	return {
        	loading: true,
          posts: [] // add posts here so reactivity is working, also undefined would be OK
        }
      },
      created() {
      	//this.loading = true --> not needed already set in data
      	axios.get(URL).then((response) => {
        	// console.log(response.data, this)
          this.posts = response.data
          this.loading = false
        })
      }
    })
    
    */
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.js"></script>
    <div id="app">
      <div v-if="loading">
        loading...
      </div>
      <div v-else>
        <ul>
          <li v-for="post in posts">
            <h1>
              {{post.title}}
            </h1>
            <p>
              {{post.body}}
            </p>
          </li>
        </ul>
      </div>
    </div>

    【讨论】:

    • 调用this.$store.dispatch('loadData')的组件怎么知道数据已经加载?我们可以通过changeLoadingState 进行检查,但是如果发生了很多加载怎么办?
    • 如果我理解正确,您可以检查loading 状态,如果您想做多个请求,您可以使用Promise.all 等待所有请求解决,然后调用commit('changeLoadingState', false)loading 状态更改为 false。 this.$store.dispatch 在创建 Vue 实例时只调用一次。
    猜你喜欢
    • 2020-12-23
    • 2021-01-12
    • 2021-09-05
    • 1970-01-01
    • 2020-09-10
    • 2021-05-03
    • 1970-01-01
    • 2017-06-09
    • 2021-02-07
    相关资源
    最近更新 更多