【问题标题】:Calling a component function from the store once an action is complete in Vuex在 Vuex 中完成操作后从 store 中调用组件函数
【发布时间】:2019-03-29 14:05:08
【问题描述】:

我试图在添加新元素后自动滚动到包含元素列表的 div 的底部。

由于添加和删除元素是通过 Axios 使用 API 完成的,因此我必须等待服务器的响应才能更新我在 Vuex 中的状态。

这意味着,一旦在我的状态中添加了一个元素,每次我调用“scrollDown”函数时,该函数都会滚动到倒数第二个元素(由于异步Axios调用不是尚未注册)。

我的问题是,如何等待 Vuex 中的操作完成,然后调用组件中的函数滚动到 div 的底部?

我尝试使用观察者、计算属性、发送道具、跟踪 Vuex 中实际状态的变化,但这些都不起作用......

// VUEX

const state = {
  visitors: [],
  url: 'API URL',
  errors: []
}
const mutations = {
  ADD_VISITOR(state, response) {
    const data = response.data;
    data.Photos = [];
    state.visitors.data.push(data);
  },
}
const actions = {
  addVisitor: ({ commit }, insertion) => {
    axios
      .post(state.url + 'api/visitor', {
        name: insertion.visitorName
      })
      .then(response => {
        commit('ADD_VISITOR', response);
      })
      .catch(error => state.errors.push(error.response.data.message));
    state.errors = [];
  },
}

// MY COMPONENT FROM WHERE THE ACTIONS ARE BEING DISPATCHED

<div ref="scroll" class="visitors-scroll">
  <ul v-if="visitors.data && visitors.data.length > 0" class="list-group visitors-panel">
    <!-- Displaying appVisitor component and sending data as a prop -->
    <app-visitor v-for="visitor in visitors.data" :key="visitor.id" :visitor="visitor"></app-visitor>
  </ul>
</div>

methods: {
  // Function that dispatches the "addVisitor" action to add a new visitor to the database
  newVisitor() {
    const insertion = {
      visitorName: this.name
    };
    if (insertion.visitorName.trim() == "") {
      this.errors.push("Enter a valid name!");
    } else {
      this.$store.dispatch("addVisitor", insertion);
      this.name = "";
    }
    this.errors = [];
    this.scrollDown(); // I WANT TO CALL THIS FUNCTION WHEN AXIOS CALL IS FINISHED AND MUTATION IN VUEX IS COMPLETED
  },
  scrollDown() {
    this.$refs.scroll.scrollTop = this.$refs.scroll.scrollHeight;
  }
},

感谢任何帮助!

【问题讨论】:

    标签: javascript vue.js vuejs2 vuex


    【解决方案1】:

    在 vuex 中调度的动作返回一个 Promise。如果您的代码是空的 Promise,因为没有什么可以返回。您需要返回/传递您的 axios Promise,然后在您的组件中等待它。看看这个固定的代码:

    // VUEX
    
    const state = {
      visitors: [],
      url: 'API URL',
      errors: []
    }
    const mutations = {
      ADD_VISITOR(state, response) {
        const data = response.data;
        data.Photos = [];
        state.visitors.data.push(data);
      },
    }
    const actions = {
      addVisitor: ({ commit }, insertion) => {
        return axios
          .post(state.url + 'api/visitor', {
            name: insertion.visitorName
          })
          .then(response => {
            commit('ADD_VISITOR', response);
          })
          .catch(error => state.errors.push(error.response.data.message));
        state.errors = [];
      },
    }
    
    // MY COMPONENT FROM WHERE THE ACTIONS ARE BEING DISPATCHED
    
    <div ref="scroll" class="visitors-scroll">
      <ul v-if="visitors.data && visitors.data.length > 0" class="list-group visitors-panel">
        <!-- Displaying appVisitor component and sending data as a prop -->
        <app-visitor v-for="visitor in visitors.data" :key="visitor.id" :visitor="visitor"></app-visitor>
      </ul>
    </div>
    
    methods: {
      // Function that dispatches the "addVisitor" action to add a new visitor to the database
      newVisitor() {
        const insertion = {
          visitorName: this.name
        };
        if (insertion.visitorName.trim() == "") {
          this.errors.push("Enter a valid name!");
        } else {
          this.$store.dispatch("addVisitor", insertion)
            .then(() => {
               this.scrollDown();
             })
          this.name = "";
        }
        this.errors = [];
      },
      scrollDown() {
        this.$refs.scroll.scrollTop = this.$refs.scroll.scrollHeight;
      }
    },
    

    【讨论】:

    • 谢谢,这太完美了。
    【解决方案2】:

    您可以尝试使用async/await 语法。

    这意味着当它会等到this.$store.dispatch("addVisitor", insertion)被解析时,这意味着直到来自API的响应出现,下一行代码将不会被执行。

    methods: {
      // Function that dispatches the "addVisitor" action to add a new visitor to the database
      async newVisitor() {
        const insertion = {
          visitorName: this.name
        };
        if (insertion.visitorName.trim() == "") {
          this.errors.push("Enter a valid name!");
        } else {
          await this.$store.dispatch("addVisitor", insertion);
          this.name = "";
        }
        this.errors = [];
        this.scrollDown();
      },
      scrollDown() {
        this.$refs.scroll.scrollTop = this.$refs.scroll.scrollHeight;
      }
    }
    

    编辑:在您的 Vueux 操作中,确保添加 return 语句。

    const actions = {
      addVisitor: ({ commit }, insertion) => {
        return axios
          .post(state.url + 'api/visitor', {
            name: insertion.visitorName
          })
          .then(response => {
            commit('ADD_VISITOR', response);
          })
          .catch(error => state.errors.push(error.response.data.message));
        state.errors = [];
      },
    }
    

    【讨论】:

    • 直到我在 Vuex 中的操作中添加了“return”关键字后,这才起作用。但绝对也是一个很好的解决方案。谢谢
    • 不客气。很好,我没有注意到您的操作没有返回声明。我将编辑我的答案以更正它。
    • 不错的解决方案,谢谢
    猜你喜欢
    • 2020-07-01
    • 2022-01-23
    • 2018-11-30
    • 2018-09-12
    • 2019-08-16
    • 2018-08-10
    • 2016-08-28
    • 1970-01-01
    • 2017-12-17
    相关资源
    最近更新 更多