Vue JS изменить кнопку отправки в случае ошибки - PullRequest
0 голосов
/ 11 декабря 2018

Используя Vuex, у меня есть форма, которую при нажатии кнопки (@ click = "loader (true)") отправляет мутации загрузчика, чтобы изменить загрузку на true, которая затем устанавливает класс is-loading с Bulma CSS в true('is-loading': $ store.state.index.loading).

Затем я получаю ошибки от сервера, если форма пуста с ошибками. Это нормально работает с входными данными, но как мне это сделать?затем установите для класса 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 голосов
/ 11 декабря 2018

Во-первых, нет необходимости иметь только локально необходимое состояние (загрузка) в глобальном состоянии (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>
0 голосов
/ 12 декабря 2018

если вы используете vuex, как это.Я думаю, вы неправильно поняли Vuex.Потому что вы можете использовать для локальной переменной, и вы можете проверить результат API.если вы хотите отдельный запрос API, вы должны mapAction в методах и mapGetters в Computed

0 голосов
/ 11 декабря 2018

Вопрос об использовании ...mapMutations, но в случае, если кто-то захочет добавить бизнес-логику, рекомендуются mapAction и mapState.Я объясню, как заставить его работать с mapAction и mapState, поскольку вызов API может включать использование бизнес-логики в вашем приложении.В противном случае, я бы сказал, почему вы вообще не пользуетесь VueX, за исключением уведомления другой части вашего приложения о том, что вы загружаете;).При этом, вот мой ответ.

Используя ...mapState, вы получите то, что искали бы, computed реактивность состояния.Это произошло бы особенно во время вызова действия.Затем действие будет меняться, или то, что мы называем commit в VueX, - состояние (см. Документ: 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, а затем свойството, на что вы можете реагировать, будет «загружаться».

Во время использования обещаний, во время вашего post или get или любого другого HTTP-вызова rest, не забывайте контекст.Если вы используете 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...