$ emit从孩子到父母,简单的递增计数器会导致无限循环

时间:2018-06-29 12:41:26

标签: javascript vue.js vue-component

我要填写一个空白的问题。每次输入正确时,我都希望发回给父级,以便在所有输入正确时都可以显示成功消息。

我认为每次$ em​​it到达父级时,我都可以使用一个简单的计数器来加一,但是总是在最后一次尝试中遇到无限循环。我不明白我在做什么错。我试图尽可能地去除文件  尽可能显示出我认为相关的内容,您可以了解其工作原理。问题与父母的循环方式有关吗?

感谢您提供的任何帮助。

父组件

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

父级出现问题的部分是问题questionSuccess()

<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="questionSuccess">
     </component>
   </div>
</template>

<script>
export default {

name: "iv-v1",
props: ['cData'],
components: {
   ivInput,
   ivText,
},
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 () {
    let questionText = this.cData.body.questionText;
    //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"
        type="text"
        class="iv-input"
        v-model="userInput"
        :class="[{'is-correct':isCorrect, 'is-error':isError}]"
        :disabled="isCorrect">
    </div>
</template>
<script>
export default {
   name: "iv-input",
  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>

1 个答案:

答案 0 :(得分:0)

答案实际上非常简单。

在父组件上,我在事件上添加了.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>