0

我想创建一个简单的游戏来帮助孩子们阅读,实际上它是一种名为“静音模式”的语言学习方法,无论如何这是 jsfiddle 链接

https://jsfiddle.net/raminSafari/b7zhc98q/19/

例如,如果我希望学生首先阅读“笔”,我指向 p(1),然后指向 e(2),最后指向 n(3),代码适用于具有唯一字母的单词,但是当单词类似于“爸爸”它没有按我想要的方式工作,我希望它显示 d(1)(3), a(2)

这是完整的简化代码(我知道它不健壮)

<template>
    <div class = "container pt-5 mt-5">
            <h1 class="text-center pb-5"><span style="color: red;"> {{ answer }} </span> just to clarify</h1> <!-- just to clarify -->
    
   

        
        <div class="text-center">
        <template id="keyboard" v-for="alphabet in alphabets" >
            <template v-if = "alphabet == word.first ">
                    <span :class="{ 'active': firstActive, alphabet}"> {{ alphabet }} </span>&nbsp;<strong style="color: red; font-size: 10px;">{{ num1 }}</strong>&nbsp;
            </template>
             <template v-else-if = "alphabet == word.second ">
                   <span :class="{ 'active': secondActive, alphabet}"> {{ alphabet }} </span>&nbsp;<strong style="color: red; font-size: 10px;">{{ num2 }}</strong>&nbsp;
            </template>
             <template v-else-if = "alphabet == word.third ">
                   <span :class="{ 'active': thirdActive, alphabet}"> {{ alphabet }} </span>&nbsp;<strong style="color: red; font-size: 10px;">{{ num3 }}</strong>&nbsp;
            </template>
           
             <template v-else-if = "alphabet == word.forth ">
                   <span :class="{ 'active': forthActive, alphabet}"> {{ alphabet }} </span>&nbsp;<strong style="color: red; font-size: 10px;">{{ num4 }}</strong>&nbsp;
            </template>
             <template v-else-if = "alphabet == word.fifth ">
                   <span :class="{ 'active': forthActive, alphabet}"> {{ alphabet }} </span>&nbsp;<strong style="color: red; font-size: 10px;">{{ num5 }}</strong>&nbsp;
            </template>
            <template v-else>
                <span class="alphabet"> {{ alphabet }} </span>&nbsp;
            </template>
        </template>
       

                 <div><button class = "btn btn-info mt-3" @click = "again">again</button></div>
        </div>
           
            
     </div>
</template>

<script>
export default {
     data(){
        return{
         
           alphabets: ["p", "e", "m", "n", "d", "a", "s"],
           firstActive: false,
           secondActive: false,
           thirdActive: false,
           forthActive: false,
           fifthActive: false,
           index: 0,
           words:[
                {
                    first: 'p',
                    second: 'e',
                    third: 'n',
                    forth: '',
                    fifth: '',
                    answer : 'pen'
                },
                {
                    first: 'm',
                    second: 'a',
                    third: 'd',
                    forth: 'e',
                    fifth: '',
                    answer : 'made'
                },
                {
                    first: 'd',
                    second: 'a',
                    third: 'd',
                    forth: '',
                    fifth: '',
                    answer : 'dad'
                },

           ],
           word: [],
            answer: '', 
            myVar1: null,
            myVar2: null,
            myVar3: null,
            myVar4: null,
            myVar5: null,
            num1: '',
            num2: '',
            num3: '',
            num4: '',
            num5: ''
                     
        }
    },

    methods: {

        shuffle(a) {
                for (let i = a.length - 1; i > 0; i--) {
                    const j = Math.floor(Math.random() * (i + 1));
                    [a[i], a[j]] = [a[j], a[i]];
                }
        
                return a;
            },

            getWord(){
                this.word = this.words[this.index];
                this.answer = this.word.answer;
            },

            again(){
                clearTimeout(this.myVar1);
                clearTimeout(this.myVar2);
                clearTimeout(this.myVar3);
                clearTimeout(this.myVar4);
                clearTimeout(this.myVar5);
                this.firstActive = false;
                this.secondActive = false;
                this.thirdActive = false;
                this.forthActive = false;
                this.fifthActive = false;
                this.num1 = '';
            this.num2 = '';
            this.num3 = '';
            this.num4 = '';
            this.num5 = '';
                if(this.index == this.words.length){
                    this.index = 0;
                }else{
                    this.index++;
                }
                this.getWord();
                this.showBorder();
            },


            showBorder(){
                     this.myVar1 =  setTimeout(() => {
                         this.firstActive = true;
                         this.num1 = 1;
                    }, 2000);

                     this.myVar2 =  setTimeout(() => {
                         this.secondActive = true;
                         this.num2 = 2;
                    }, 4000);

                    this.myVar3 =  setTimeout(() => {
                         this.thirdActive = true;
                         this.num3 = 3;
                    }, 6000);

                    this.myVar4 =  setTimeout(() => {
                         this.forthActive = true;
                         this.num4 = 4;
                    }, 8000);

                    this.myVar5 =  setTimeout(() => {
                         this.fifthActive = true;
                         this.num5 = 5;
                    }, 10000);
            }
       


    },
    

   
     created(){
            
         this.words = this.shuffle(this.words);
         this.getWord();
         this.showBorder();
                                
      }

      



}
</script>

<style>
    span.alphabet{
         display: inline-block;
         width: 70px;
         height: 70px;
        
        font-size: 30px;
        font-weight: 600;
    }
    .active{
        border: 2px solid red;
        border-radius: 50%;
    }
</style>

谢谢你

4

2 回答 2

0

答案不仅仅是复制粘贴代码,而且有点长。如果您不想阅读,您可以直接跳到结论。

我阅读了 jsfiddle,这里有一些解决您面临的问题的建议:

1.将数字视为字符串,而不是数字

之后,你就会知道 d(1)(3) 问题不是显示 2 个数字,而是如何附加字符串 "1" 和 "3"并显示它。

2. 分而治之

将您的整个任务分为 3 个部分:

  1. 创建函数来控制应突出显示哪些字母并显示相应的序列。
  2. 创建一个组件,仅用于显示字母表和序列,例如 d(1)(3)。
  3. 定义函数以触发渲染过程并重置应用程序状态。

应用程序.vue

这就是数据的样子App.vue

data: function() {
    return {
        word: "dad",
        alphabets: ["p", "e", "m", "n", "d", "a", "s"],
        hits: ["", "", "", "", "", "", ""],
        handlers: [],
        delay: 2000,
    }
},

this.hits将存储命中的相应序列。例如,对于dad的情况,命中最终将变为:["", "", "", "", "13", "2", ""]

这些是您应该拥有的功能App.vue

  • 循环每个字符。中this.word,并做相应的渲染
renderAnswer: function() {
    var self = this;
    for (var i = 0; i < this.word.length; i++) {
        self.doSetTimeout(i, self);
    }
}
  • 控制何时进行渲染
doSetTimeout: function (i, self) {
    self.handlers.push(setTimeout(function () { 
        self.updateHits(i, self) 
    }, self.delay * i));
}
  • 更新hits数组,这将在每个字母上触发相应的渲染
updateHits: function(i, self) {
    let char = self.word[i];
    let index = self.alphabets.indexOf(char);
    console.debug(char, index)
    self.hits[index] += (i + 1);
    self.hits = self.hits.filter(x => true); // force refresh list for binding
}

将您的大功能划分为一些较小的功能,让它们中的每一个只做件事。

注意:在这里,您将看到renderAnswer()calldoSetTimeout()doSetTimeout()calls updateHits()。为了正确获取数据和函数,我们需要定义var self = this并传递self给每个函数调用。

字母表的子组件

在 App.vue 的模板中,需要定义一个<alphabet>子组件。该组件仅负责渲染特定字母表和与该字母表相关的序列。

<alphabet 
    v-for="(char, index) in alphabets" 
    v-bind:key="char" 
    :alphabet="char" 
    v-bind:hits="hits[index]"
/>

您需要将字母表和相应的命中值传递给子组件才能正确呈现组件。这个子组件的代码应该是直截了当的,所以我将在这里跳过。在做这部分的时候,你可能需要props官方文档中了解如何通过和使用。

运行应用程序

当你设置好所有的功能和子组件后,你应该可以dad在触发时渲染 的情况renderAnswer()

重置状态

您可能需要为每个新词重置应用程序状态。因此,您还应该定义一个reset()函数来更新this.word为一个新单词,并将每个项目重置this.hits为空字符串。

如果您需要上述步骤的更多详细信息,请阅读此要点。

结论

当您在编码方面遇到一些问题时,您可以尝试重新解决您遇到的问题。提出正确的问题将引导您使用更好的方法来解决它们。

另一方面,把问题分解成更小的问题,一个一个地解决。在这种情况下,尝试将大函数拆分为一些更小更简单的函数。并且,尝试创建一个子组件来完成渲染部分,同时将所有逻辑留给其父组件。

希望你能解决你遇到的问题,帮助更多的孩子:)

于 2020-07-17T16:38:30.903 回答
0

您可以将输入的字母存储在一个数组中,这样您就可以获得输入的字母的索引并显示它们。我建议您像这样构建您的代码。这是重构代码的小提琴https://jsfiddle.net/tk41d0wo/

<div id="app">
  <div>
    Current word is <span style="color: red;">{{ words[currentIndex] }}</span>
  </div>
  <div>
     <button 
       v-for="letter in letters" 
       :key="letter" 
       @click="inputLetter(letter)"
       :style="{ color: (inputs.includes(letter)) ? 'red': 'initial' }"
     >
       {{ letter }} <small>({{ getAllLetterPositions(letter).join(', ') }})</small>
     </button>
  </div>
  <button @click="resetInputs">
    Reset
  </button>
</div>

在你的组件中......

new Vue({
  el: "#app",
  data: {
    currentIndex: 0,
    words: ['made', 'sad', 'dad'],
    letters: ['p', 'e', 'm', 'n', 'd', 'a', 's'],
    inputs: [],
  },
  methods: {
    inputLetter(letter) {
      this.inputs.push(letter);
        if(this.inputs.join('') == this.words[this.currentIndex]) {
        this.currentIndex++;
        this.resetInputs();
      }
    },
    getAllLetterPositions(letter) {
        return this.inputs.reduce((positions, current, index) => {
        if(current == letter) {
            return positions.concat(index + 1);
        }
        return positions;
      }, []).sort(function(a, b){return a-b})
    },
    resetInputs() {
        this.inputs = [];
    }
  }
})
于 2020-07-17T16:53:47.620 回答