如果发生错误,Vue JS更改提交按钮

时间:2018-12-11 15:00:23

标签: javascript vue.js vuex

使用Vuex,我有一种形式,当单击按钮时(@ click =“ loader(true)”)发送到loader突变以将load更改为true,然后将Bulma CSS的is-loading类设置为true (“正在加载”:$ store.state.index.loading)。

如果表单为空,且有errors.title,那么我会从服务器收到错误,这在输入中可以正常工作,但是如果出现错误,我该如何将is-loading类设置为false?

(如果运行该代码段,则该代码段将不起作用)

export const state = () => ({
  loading: false
});

export const mutations = {
  loader(state, value) {
    state.loading = value;
  }
 }
<form @submit.prevent="postThis">

  <div class="field">
    <div class="control">
      <input class="input" :class="{ 'is-danger': errors.title }" type="text" id="title" placeholder="I have this idea to..." autofocus="" v-model="newTitle">

    </div>
    <p class="is-size-6 help is-danger" v-if="errors.title">
      {{ errors.title[0] }}
    </p>
  </div>

  <div class="field">
    <div class="control">

      <button @click="loader(true)" type="submit" :class="{'is-loading' : $store.state.index.loading }">
        Post
      </button>


    </div>
  </div>
</form>

<script>
  import {mapMutations,} from 'vuex';
  methods: {
    ...mapMutations({
      loader: 'index/loader'
    })
  }
</script>

3 个答案:

答案 0 :(得分:2)

问题是有关使用...mapMutations的问题,但是如果有人想添加业务逻辑,则建议使用mapActionmapState。我将说明如何使其与mapActionmapState一起使用,因为调用API可能涉及在应用程序中使用业务逻辑。否则,我会说,为什么除了通知应用程序的其他部分正在加载之外,您还要使用VueX?话虽如此,这是我的答案。

使用...mapState,您可以搜索到computed状态的状态。尤其是在调用动作期间,会发生这种情况。然后动作将发生变化,或者我们在VueX中称为状态的commit(请参阅doc:https://vuex.vuejs.org/guide/state.html

让我们将您的代码更改为具有名称空间的模块,然后在您的vue中使用该模块(如果应用程序很大,我会这样做,否则可以通过使用突变或不使用VueX来实现相同的功能全部):

const LOADING_STATE = 'LOADING_STATE'
export default {
  namespaced: true, // Read the doc about that

  state: {
    loaded: false
  },

  mutations: {
    [LOADING_STATE]: function (state, isLoading) {
      state.loading = isLoading
    }
  },

  actions: {
    setLoading ({ commit }, isLoading) {
      commit(LOADING_STATE, isLoading)
    }
  }
}

对于您的 vue 文件,其中包含模板和操作。看起来像这样:

<script>
  import { mapAction, mapState } from 'vuex'

  exports default {
     computed: {
        ...mapState({
          // Here you could even have the full computation for the CSS class.
          loading: state => state.loadingModule.loading,

          // Like this... or you could use the getters that VueX does (search in the documentation since it's out of the scope of your question)
          loadingCss: state => { return state.loadingModule.loading ? 'is-loading' : '' }
        })
      },
     methods: {
         // Usage of a namespace to avoid other modules in your VueX to have the same action.
         ...mapActions(['loadingModule/setLoading']),
     }
  }
</script>

关于html模板,您将能够调用方法this['loadingModule/setLoading'](true)false,然后您可以响应的属性将被“加载”。

在使用postget 任何其他HTTP Rest调用期间,使用Promise时,请不要忘记上下文。如果您使用的是Axios,请在您的VueJs上下文中注册后,我会做

this.$http.get('/my/api')
   .then(response => { 
      // ... some code and also set state to ok ... 
   })
   .catch(e => { 
      // set state to not loading anymore and open an alert 
   })

考虑到您正在某个地方进行HTTP(S)调用,现在就完成您的代码。

<form @submit.prevent="postThis">

  <div class="field">
    <div class="control">
      <!-- Here I would then use a computed property for that class (error). I would even put the a template or a v-if on a div in order to show or not all those html elements. That's you're choice and I doubt this is your final code ;) -->
      <input class="input" :class="{ 'is-danger': errors.title }" type="text" id="title" placeholder="I have this idea to..." autofocus="" v-model="newTitle">
    </div>

    <p class="is-size-6 help is-danger" v-if="errors.title">
      {{ errors.title[0] }}
    </p>
  </div>

  <div class="field">
    <div class="control">
      <button @click="['loadingModule/setLoading'](true)" type="submit" :class="{'is-loading' : loading }">
        Post
      </button>
    </div>
  </div>
</form>

答案 1 :(得分:0)

首先,无需在全局状态(Vuex)中仅具有本地所需的状态(正在加载)。因此,典型用法如下:

<template>
  <form>
    <div class="field">
      <div class="control">
        <input
          class="input" :class="{ 'is-danger': errors.title }"
          type="text"
          id="title"
          placeholder="I have this idea to..."
          autofocus=""
          v-model="newTitle"
        >
      </div>
      <p class="is-size-6 help is-danger" v-if="errors.title">
        {{ errors.title[0] }}
      </p>
    </div>
    <div class="field">
      <div class="control">
        <button
          @click="postForm"
          :class="{'is-loading': isLoading }"
        >
          Post
        </button>
      </div>
    </div>
  </form>
</template>

<script>
export default {
  ...
  data () {
    return {
      ...
      newTitle: '',
      isLoading: false,
      response: null
    }
  },

  methods: {
    async postForm () {
      try {
        this.isLoading = true // first, change state to true
        const { data } = await axios.post('someurl', { title: this.newTitle }) // then wait for some async call
        this.response = data // save the response
      } catch(err) {
        // if error, process it here
      } finally {
        this.isLoading = false // but always change state back to false
      }
    }
  }
}
</script>

答案 2 :(得分:-1)

如果您使用vuex这样的话。我想你误会了Vuex。因为您可以使用局部变量,并且可以检查api结果。如果您需要单独的api请求,则必须在方法中使用mapAction并在Computed中使用mapGetters