【问题标题】:Vue JS change submit button if errors如果错误,Vue JS 更改提交按钮
【发布时间】:2019-05-12 14:28:22
【问题描述】:

使用 Vuex 我有一个表单,当单击按钮时 (@click="loader(true)") 发送到加载程序突变以将加载更改为 true,然后将带有 Bulma CSS 的 is-loading 类设置为 true ('is-loading' : $store.state.index.loading )。

如果表单为空且带有errors.title,然后我会从服务器收到错误,这适用于输入,但如果有错误,我如何将is-loading 类设置为false?

(如果你运行它,代码 sn-p 将不起作用)

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>

【问题讨论】:

  • 在这种情况下,您可能需要使用一个操作,根据服务器的响应将 state.loading 的值切换为 false。
  • 不要引用我的话,但应该是类似于this.$store.commit('loader', false) 的内容。 vuex.vuejs.org/guide/mutations.html
  • 哦。等待。我误读了。在您的postThis 方法中进行一些验证或try { } catch { }。如果您可以向我们公开该方法,可以尝试并提供进一步帮助。
  • postThis 如果使用promise,你应该对突变、状态、动作的逻辑和使用没问题。如果您有业务逻辑,则直接使用突变是不好的。我实际上会将业务逻辑放在您的操作中,然后使用提交来管理所有状态。提交(加载)然后提交(失败)或提交(完成与成功)。那么你只有一种方法可以调用。由你决定正确使用 vuex ;)
  • 是的,使用 commit('loader', true) 将突变移动到操作中是有意义的,但如果您没有其他需要,那么直接使用突变并没有错,只需更改状态,这显然是例如而不是把完整的行动方法

标签: javascript vue.js vuex


【解决方案1】:

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

使用...mapState,您可以获得您要搜索的内容,即状态的computed 反应性。这尤其会在调用动作期间发生。然后动作将发生变化,或者我们在 VueX 中称为 commit 的状态(参见文档: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,然后您可以响应的属性将是“正在加载”。

在使用 Promise 时,在您的 postget 任何其他 HTTP 休息调用期间,不要忘记上下文。如果您使用的是 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>

【讨论】:

    【解决方案2】:

    首先,在全局状态 (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>
    

    【讨论】:

    • 查看 mdn 文档以了解 try ... catch 和 async / await
    • 用你的实际代码提出另一个问题,这是一个难以理解的混乱。
    【解决方案3】:

    如果你像这样使用 vuex。我猜你误解了vuex。因为你可以使用局部变量,你可以检查 api 结果。如果你想要单独的 api 请求,你必须在方法中使用 mapAction,在计算中使用 mapGetters

    【讨论】:

    • 您不必映射任何可以直接调用突变或状态的东西,map 是一种扩展运算符,当您有多个操作或 getter 时使用它,也许您误解了 Vuex 的灵活性
    • vuex.vuejs.org 有 vuex lifecyle vuex.vuejs.org/vuex.png 如果你检查你就会明白什么在做动作和突变
    猜你喜欢
    • 2017-02-03
    • 2021-10-04
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多