首页 > 解决方案 > 如何将异步等待添加到 vuex 操作?

问题描述

我正在尝试将一些数据发布到 vue 中的端点,然后在成功时执行一个操作并在前端异步返回数据,以便其无缝并按预期更新并为用户提供反馈。

我下面的代码在 vue 中有一堆动作,它们共同构建流程的每个部分。该CREATE_FOLDER: function ({ commit },payload)函数是执行第一部分的主要函数。

然后我检查响应,如果它通过了,我们运行这个动作commit('SET_FOLDER_LIST', { list: response.data }),它是这里主要功能的一部分:

CREATE_FOLDER: function ({ commit },payload) {

      const config = {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded','accept': 'application/json' }
      };
      const params = new URLSearchParams();
      params.append('folderName', payload);

      axios.post(
        process.env.MIX_SCRAPBOOK_API_BASE+'rest/user/folder/', 
        params,
        config
      )
      .then(function (data) {
        axios.get(process.env.MIX_SCRAPBOOK_API_BASE+'rest/user/folder').then(response => {
          commit('SET_FOLDER_LIST', { list: response.data })
          commit('SET_GLOBAL_FOLDER_LIST', { list: response.data })
        }, (err) => {
          console.log(err)
        })
      })
      .catch(function (error) {
        console.log(error);
      });

    }

我需要做的是能够更新端点并能够获取该数据并立即在前端显示它。这是如何在 vue 中完成的?

所有代码如下:

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

const debug = process.env.NODE_ENV !== 'production'

const store = new Vuex.Store({
  state: {
    folders: {
      subFolders: [],
      contentDetails: {
        articles: []
      }
    },
    allFolders: [],
    subFolders: {
      subFolders: [],
      contentDetails: {
        articles: []
      }
    },
    readingList: [],
    readingItem: [],
    shared: {
      subFolders: [],
      contentDetails: {
        articles: []
      }
    },
    selectedItems: []
  },
  actions: {
    async LOAD_FOLDERS_LIST({ commit }) {
      const config = {
        headers: {'Cache-Control' : 'no-cache'}
      };
      await axios.get(process.env.MIX_SCRAPBOOK_API_BASE+'rest/user/folder').then(response => {
        commit('SET_FOLDER_LIST', { list: response.data })
        commit('SET_GLOBAL_FOLDER_LIST', { list: response.data.subFolders })
      }, (err) => {
        console.log(err)
      })
    },
    async LOAD_SUBFOLDERS_LIST({ commit },payload) {
      await axios.get(process.env.MIX_SCRAPBOOK_API_BASE+'rest/user/folder/'+payload).then(response => {
        commit('SET_SUBFOLDER_LIST', { subfolderlist: response.data })
        commit('SET_GLOBAL_FOLDER_LIST', { list: response.data.subFolders })
      }, (err) => {
        console.log(err)
      })
    },
    CREATE_FOLDER: function ({ commit },payload) {

      const config = {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded','accept': 'application/json' }
      };
      const params = new URLSearchParams();
      params.append('folderName', payload);

      axios.post(
        process.env.MIX_SCRAPBOOK_API_BASE+'rest/user/folder/', 
        params,
        config
      )
      .then(function (data) {
        axios.get(process.env.MIX_SCRAPBOOK_API_BASE+'rest/user/folder').then(response => {
          commit('SET_FOLDER_LIST', { list: response.data })
          commit('SET_GLOBAL_FOLDER_LIST', { list: response.data })
        }, (err) => {
          console.log(err)
        })
      })
      .catch(function (error) {
        console.log(error);
      });

    }
  },
  mutations: {
    SET_FOLDER_LIST: (state, { list }) => {
      state.folders = list
    },
    SET_GLOBAL_FOLDER_LIST: (state, { list }) => {
      state.allFolders = list
    },
    SET_SUBFOLDER_LIST: (state, { subfolderlist }) => {
      state.subFolders = subfolderlist
    }
  },
  getters: {
    openFolders: state => {
      return state.folders
    },
    openReadingList: state => {
      return state.readingList
    },
    openSharedData: state => {
      return state.shared
    },
    openReadingItem: state => {
      return state.readingItem
    },
    openSubFolders: state => {
      return state.subFolders
    },
    selectFolder: state => {
      return state.selectedFolder
    },
    selectedItems: state => {
      return state.selectedItems
    },
    allFolders: state => {
      return state.allFolders
    }
  }
})
export default store

组件本身

<template lang="html">
  <div>
    <!-- Folders -->
    <div class="flex-none w-100 mv3 gray folders"><div class="ph4"><p>Bookmarks({{folders['contentDetails'].articles.length}})</p></div></div>
    <div class="flex flex-row flex-wrap justify-start items-start folders mb6">

        <div v-for="article in folders['contentDetails'].articles" class="fl w-25-ns w-100 pl4 pointer article-item relative mb4">
          <a v-on:click.stop.prevent="checkFolder(article)" :class="[{highlight:selectedItems.includes(article)}, 'absolute right-2 top-2 z-3 activeToggle']" href="#"></a>
          <a class="link" v-bind:href="article.contentUrl">
            <div class="content flex justify-between no-margin">
              <p class="f3 mb3">{{article.contentType}}</p>
              <p class="f3 mb3">{{article.createdDate | moment("ddd, MM YYYY")}}</p>
            </div>
            <div class="contentImage">
              <img class="w-100" :src=article.titleImage data-flickity-lazyload="article.titleImage">
            </div>
            <div class="black">
              <h4 class="f3">{{article.contentTitle}}</h4>
            </div>
            <div class="content no-margin">
              <p class="f3">Saved on <span class="text-orange">{{article.savedDate | moment("ddd, MM YYYY")}}</span></p>
            </div>
          </a>
        </div>

    </div>

    <div v-if="folders['subFolders']">
    <div class="flex flex-row flex-wrap justify-start items-start folders">
      <div class="w-third-ns w-100 pl4 folder">
        <div class="relative db h-100 bg-light-gray folder-new br3 mb4">       
          <div v-on:click="addFolder($event)" class="dt w-100 h-100 top aspect-ratio--object">
            <div class="dtc v-mid tc no-margin showText pv6">
              <svg class="dib v-mid icon-sprite" width="40" height="40">
                <use class="no-barba" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/images/icons.svg#plus"></use>
              </svg>
              <p>New Folder</p>
            </div>
          </div>
          <div class="dt w-100 h-100 bottom aspect-ratio--object">
            <div class="dtc v-mid tc no-margin showText pv6">
              <p>Explore the library and add to this folder</p>
              <svg class="dib v-mid icon-sprite" width="40" height="40">
                <use class="no-barba" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/images/icons.svg#open-arrow"></use>
              </svg>
              <form id="submit-folder" @submit.prevent="sendForm">
                <input type="text" name="folderName" value="" placeholder="Add folder name in here..." v-model="folderName">
                <input class="db center input-reset bg-orange b--none br2 white mv3 f3 pv3 ph4" style="font-family:'Open Sans',Helvetica Neue,sans-serif;" type="submit" name="Submit">
              </form>
            </div>
          </div>
        </div>
      </div>
      <div v-for="folder in folders['subFolders']" class="w-third-ns w-100 pl4 pointer folder relative">
        <a v-on:click.stop="checkFolder(folder.uuid)" :class="[{highlight:selectedItems.includes(folder.uuid)}, 'absolute right-2 top-2 z-3 activeToggle']" href="#"></a>
        <router-link :to="`/folders/${folder.uuid}`">
          <div class="image-blocks br3 overflow-hidden relative">

              <div class="" v-for="image in folder.topThreeThumbnails">
                <img class="" :src=image>
              </div>

          </div>
        </router-link>
        <div class="content">
          <router-link :to="`/folders/${folder.uuid}`" class="link">
            <h3>{{folder.folderName}}</h3>
            <p>{{folder.subFolderCount}} subfolders, {{folder.totalElements}} elements</p>
          </router-link>
        </div>
      </div>
    </div>
  </div>
</div>
</template>

<script>
import { mapState } from 'vuex'
import Slick from 'vue-slick'
export default {
  name: 'folderList',
  data() {
    return {
      selected: [],
      isSelected: false,
      foldersLength: '',
      folderName: '',
      slickOptions: {
          slidesToShow: 5,
          slidesToScroll: 1,
          dots: true,
          adaptiveHeight: false,
          infinite: true,
          centerMode: false,
          focusOnSelect: true,
          speed: 700,
          useTransform: true,
          easing: 'ease-in-out',
          prevArrow: '.prev-slider',
          nextArrow: '.next-slider',
          responsive: [
            {
                breakpoint: 980,
                settings: {
                  variableWidth: true,
                  slidesToShow: 1
                }
            },
            {
                breakpoint: 769,
                settings: {
                  slidesToShow: 1,
                  dots: true,
                  arrows: false,
                  centerPadding: '0px',
                  variableWidth: false,
                  adaptiveHeight: false
                }
            },
            {
                breakpoint: 480,
                settings: {
                  slidesToShow: 1,
                  dots: true,
                  arrows: false,
                  centerPadding: '0px',
                  variableWidth: false,
                  adaptiveHeight: false
                }
            }
          ]
        },
    }
  },
  components: {
    Slick
  },
  computed: {
   ...mapState([
      'folders',
      'allFolders',
      'selectedItems',
      'selectedFolder'
    ]),
  },
  methods: {
    checkFolder: function(item){
      this.$store.dispatch('SELECT_FOLDER',item)
    },
    checkFolder: function(item){
      this.$store.dispatch('SELECT_FOLDER',item)
    },
    addFolder: function(event){
      const target = event.currentTarget.parentNode,
            top    = target.children[0],
            bottom = target.children[1];
      if(bottom.classList.contains('active')){
        top.classList.remove('hidden');
        bottom.classList.remove('active');
      } else {
        top.classList.add('hidden');
        bottom.classList.add('active');
      }      
    },
    sendForm: function(event){
      this.$store.dispatch('CREATE_FOLDER',this.folderName)
    },
    next() {
        this.$refs.slick.next();
    },

    prev() {
        this.$refs.slick.prev();
    },

    reInit() {
        // Helpful if you have to deal with v-for to update dynamic lists
        this.$nextTick(() => {
            this.$refs.slick.reSlick();
        });
    },
  },
  mounted: function () {
    this.$store.dispatch('LOAD_FOLDERS_LIST')
  },
  watch: {
    '$route': function(from, to) {
      this.$store.dispatch('LOAD_FOLDERS_LIST')
    }
  }
}

</script>

这是 vuex 状态的截图:

在此处输入图像描述

标签: javascriptvue.jsvuejs2vuex

解决方案


推荐阅读