Vuex наблюдатель ошибочно выстрелил дважды - PullRequest
0 голосов
/ 25 октября 2019

Я искал 2 часа сейчас, я понятия не имею, что я делаю неправильно ... надеюсь, кто-то может мне помочь:

в принципе, это довольно легко. У меня есть компонент многократного использования для Recaptchas. рассматриваемый элемент - это текстовое поле во всплывающем диалоговом окне для «забытого пароля» (над маской входа в систему)

. Основная идея обработки изменяющихся капч (поскольку на одной странице их две):

  • у меня есть поле vuex для каждой возможной капчи, инициализированное для null
  • для каждой кнопки отправки формы, я запускаю мутацию, которая устанавливает поле капчи на 0
  • затем у меня есть установщики-наблюдатели в компоненте recaptcha, которые прослушивают изменения, и if === 0, начинаем оценивать капчу
  • , затем onValidated, вызываем мутацию, которая сохраняет результат в vuex. другой наблюдатель с if(newVal) затем отправляет все.

в моей теории, это работает без проблем. я помню, что это уже работало в некоторый момент в прошлом (или я просто не заметил двойной отправки), но теперь я внес некоторые изменения, и это ведет себя очень странно.

, если быть точным: я нажимаюкнопка один раз, все работает нормально, НО один наблюдатель срабатывает дважды, хотя это не должно происходить вообще. все до срабатывания ОДИН РАЗ, только этот наблюдатель срабатывает дважды, даже когда я сделал

if (!this.running) {
            this.running = true
            console.log('forgot watcher 2')
            this.$refs.recaptcha.execute()
        }

, но это тоже не работает. кажется, что они запускаются в одно и то же время, что для меня не имеет смысла

вывод консоли таков:

submit
verify forgot captcha
0
forgot watcher 2
0
forgot watcher 2
verified
forgot captcha verified 03AOLTBLTP...............
forgot watcher
verified
forgot watcher

, так что легко следовать:

  • нажмите на login.vue
  • мутация устанавливает значение 0
  • watcher в recaptcha.vue замечает и запускает оценку (эта ошибка запускается дважды)
  • если проверено, verifyCaptcha() в recaptcha.vue сохраняет в vuex

мои файлы выглядят следующим образом:

login.vue

<template>
  <v-form
    @submit.prevent="twoFaRequired ? sendTwoFa() : verifyLoginCaptcha()"
  >
    // ...
   <recaptcha />
    // ...
    <v-layout>
        <form>
           // ...
           <recaptcha />
           <v-btn
              color="primary"
              :loading="forgotLoading"
              :disabled="successful || forgotLoading || $v.$invalid"
              @click.native.stop.prevent="verifyForgotCaptcha"
            >Reset Password</v-btn>

//...
  methods: {
    verifyForgotCaptcha() {
      console.log('submit')
      this.$store.commit('user/VERIFY_FORGOT_CAPTCHA')
    },
//...
  watch: {
    forgotCaptcha(newVal, oldVal) {
      if (newVal) {
        console.log('forgot watcher')
        this.sendForgotEmail()
      }
    },
//...
    forgotCaptcha() {
      return this.$store.state.user.forgotCaptcha
    },

мутации.js

//...
  VERIFY_FORGOT_CAPTCHA(state) {
    console.log('verify forgot captcha')
    state.forgotCaptcha = 0
  },
  FORGOT_CAPTCHA_VERIFIED(state, payload) {
    console.log('forgot captcha verified', payload)
    state.forgotCaptcha = payload
  },
//...

recaptcha.vue

<template>
  <div class="d-flex justify-center">
    <vue-recaptcha
      ref="recaptcha"
      :sitekey=siteKey
      :loadRecaptchaScript="true"
      size="invisible"
      @verify="verifyCaptcha">
    </vue-recaptcha>
  </div>
</template>

<script>
  import VueRecaptcha from 'vue-recaptcha'
  import { mapGetters } from 'vuex'

  export default {
    data: () => ({
      running: false,
      usage: '',
      siteKey: 'xxxxxxx'
    }),
    components: { VueRecaptcha },
    computed: {
      ...mapGetters([
        'user'
      ]),
    //...
      isForgotCaptcha() {
        return this.$store.getters['user/forgotCaptcha']
      }
    },
    methods: {
      verifyCaptcha(response) {
        console.log('verified')
    //...
          if (this.usage === 'forgot')        this.$store.commit('user/FORGOT_CAPTCHA_VERIFIED', response)
        this.usage = ''
        this.$refs.recaptcha.reset()
      }
    },
    watch: {
    //...
      isForgotCaptcha(newVal) {
        if (newVal === 0) {
          console.log('forgot watcher 2')
          this.usage = 'forgot'
          this.$refs.recaptcha.execute()
        }
      },
    }
  };
</script>

Если вам нужна дополнительная информация / код, пожалуйста, не стесняйтесь спрашивать. Я надеюсь, что кто-нибудь может сказать мне, что я делаю неправильно. Я схожу с ума здесь. спасибо!

1 Ответ

2 голосов
/ 25 октября 2019

В login.vue у вас есть два экземпляра <recaptcha>. Каждый из них будет иметь свой собственный набор наблюдателей, они не являются общими. Точно так же у каждого из них есть собственное вычисляемое свойство isForgotCaptcha.

. При изменении user/forgotCaptcha будет изменено свойство isForgotCaptcha обоих компонентов, что приведет к запуску каждого из их наблюдателей.

Настройка this.running будет устанавливать это свойство только для одного из recaptcha компонентов, оно не будет влиять на другие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...