【问题标题】:$emit from child to parent, Simple increment counter causes infinite loop$emit 从子级到父级,简单的增量计数器导致无限循环
【发布时间】:2018-06-29 12:41:26
【问题描述】:

我有一个填空题。每次输入正确时,我都想发回给父级,这样当所有输入正确时,我就可以显示成功消息。

我想我可以使用一个简单的计数器在每次 $emit 到达父级时加一,但总是在最后一次尝试时我得到一个无限循环。我不明白我做错了什么。我试图尽可能多地删除我的文件 尽可能展示我认为相关的内容,您可以了解它是如何工作的。是否与问题的父级循环方式有关?

感谢您提供的任何帮助。

父组件

父组件接受一个 JOSN 字符串,例如“*_* 字母表中有 *_* 字母”,并将其拆分为文本的跨度和 *_* 的输入,然后重新组合它。答案是 26 和英语

parent 的问题在于函数 questionSuccess()

<template>
  <div class="interactive interactive-vue-question interactive-vue-question-iv">
    <component
      :is="buildQuestion(index)"
      v-for="(item, index) in questionParts"
      ref="ivWrap"
      :key="index"
      :question-props="item.includes('*_*') ? matchedOptions[index] : item"
      @success="questionSuccess"
    />
  </div>
</template>

<script>
export default {
  name: 'IvV1',

  components: {
    ivInput,
    ivText,
  },

  props: ['cData'],

  data: function () {
    return {
      questionParts: [],
      matchedOptions: [],
      options: this.cData.body.options,
      optionsIndex: 0,
      answerBtnText: 'Show Answer(s)',
      showAnswers: false,
      showHints: false,
      showModal: false,
      counter: 0
    }
  },

  created () {
    const { questionText } = this.cData.body
    // Split the array at any whitespace character, and groups *_* an returns an array
    this.questionParts = questionText.split(/\s*(\*_\*)\s*/)
    // Filter out any empty array items so there's no extra unkown values
    this.questionParts = this.questionParts.filter(function (e) { return e })
    console.log(this.showHints)
  },

  beforeMount: function () {
    // Find all the questionParts
    for (let x = 0; x < this.questionParts.length; x++) {
      // If input placeholder is found push the corresponding answer from answers into matchedAnswers array
      if (this.questionParts[x].includes('*_*')) {
        this.matchedOptions.push(this.options[this.optionsIndex])
        this.optionsIndex++
      } else {
        // If not push an empty string
        this.matchedOptions.push('')
      }
    }
  },

  methods: {
    buildQuestion: function (index) {
      // Find the question parts that inlude *_* and push an input to array otherwise push the <span> text </span>
      if (this.questionParts[index].includes('*_*')) {
        return ivInput
      } else {
        return ivText
      }
    },

   // THIS IS WHERE I AM TRYING TO COUNT EACH TIME IT RUNS
    questionSuccess: function () {
      this.counter++
      console.log(this.counter)
    },
  }
}
</script>

输入组件

每个输入都单独验证,因此当每个输入正确时,我想将成功发送给父级。然后在父项中计算它已发出的次数,以便我可以显示一条消息,但我在最后一次正确输入时得到无限循环

我在 isCorrect() 之后发出“成功”

<template>
  <div class="iv-input-wrap" :class="[{'is-error': isError, 'is-correct': isCorrect}]">
    <input
      ref="iv"
      v-model="userInput"
      type="text"
      class="iv-input"
      :class="[{'is-correct':isCorrect, 'is-error':isError}]"
      :disabled="isCorrect"
    >
  </div>
</template>

<script>
export default {
  name: 'IvInput',

  props: [
    'cData',
    'questionProps',
  ],

  data: function () {
    return {
      userInput: '',
      errorMessage: '',
      showPadding: this.questionProps.showPadding,
      displayErrorMessage: this.cData.config.displayErrorMessage,
    }
  },

  computed: {
    isCorrect: function () {
      if (this.isType === true && this.isMatch === true) {
        this.$emit('success')

        return true
      }
    },
    isError: function () {
      // If isType has failed and displayErrorMessages are turned on return
      if (this.isType === false && this.displayErrorMessage === true) {
        this.$nextTick(function () {
          new Popper(this.$refs.iv, this.$refs.errorPopper, {
            placement: 'bottom'
          })
        })

        return true
      }
    },

    hideErrorMessage: function () {
      // If Display error message has been turned off
      if (this.isType === false && this.displayErrorMessage === false) {
        return true
      }
    },

    isType: function () {
      // If the answer type is a string
      let charRegex
      if (this.questionProps.type === 'string') {
        // Check what the accent allowed is
        if (this.questionProps.accent === true) {
          // Allow alpha and accented characters
          charRegex = /^[A-Za-z\u00C0-\u024F]+$/
          this.errorMessage = 'Letters Only'
        } else {
          // Allow alpha characters only
          charRegex = /^[A-Za-z]+$/
          this.errorMessage = 'Letters only'
        }
        // Check if the user has typed anything, if so match input to char-regex
        if (this.userInput.length > 0) {
          if (this.userInput.match(charRegex)) {
            return true
          } else {
            return false
          }
        }
      } // End if is string
    },

    isMatch: function () {
      // If isType has not passed then we don't need to proceed
      let checkCase
      if (this.isType === true) {
        checkCase = this.userInput.localeCompare(
          this.questionProps.answer, { sensitivity: 'case', usage: 'search' })
      } // end isType true
    } // end isMatch
  },
}
</script>

【问题讨论】:

    标签: javascript vue.js vue-component


    【解决方案1】:

    答案其实很简单。

    在父组件上,我在事件上添加了 .once,这会停止循环并允许它按预期递增。

    <template>
         <div class="interactive interactive-vue-question interactive-vue-question-iv">
         <component 
           :is="buildQuestion(index)"
            ref="ivWrap"
            v-for="(item, index) in questionParts"
            :key="index"
            :questionProps="item.includes('*_*') ? matchedOptions[index] : item"
             @success.once="questionSuccess">
         </component>
       </div>
    </template>
    

    【讨论】:

      猜你喜欢
      • 2020-12-09
      • 2019-08-28
      • 2018-04-15
      • 1970-01-01
      • 2021-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-14
      相关资源
      最近更新 更多