【问题标题】:vue js class binding on repetitious elementvue js类绑定在重复元素上
【发布时间】:2020-11-07 06:43:45
【问题描述】:

我想创建一个简单的游戏帮助孩子阅读,其实是一种语言学习方法,叫做“静音模式”,反正这是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>

谢谢

【问题讨论】:

    标签: vue.js vuejs2 vue-class-components


    【解决方案1】:

    您可以将输入的字母存储在一个数组中,这样您就可以获得输入的字母的索引并显示它们。我建议您像这样构建您的代码。这是重构代码的小提琴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 = [];
        }
      }
    })
    

    【讨论】:

    • 感谢@rjcarf,但这不是我想要的,我说代码适用于具有唯一字母的单词,程序显示数字例如 m(1)、a(2) 和 n(3)一年级的学生想出了它的“人”,但是你给了我一个想法来创造另一个新的简单的游戏,谢谢
    • 很高兴你喜欢它@RaminSafari。我的意思是重构你的代码也使它更短和更简单,但无论如何,愉快的编码。
    【解决方案2】:

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

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

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

    之后你就会知道d(1)(3)的问题不是显示2个数字,确实是如何追加字符串“1”和“3” 并显示它。

    2。分而治之

    把你的整个任务分成三个部分:

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

    App.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
    }
    

    把你的大函数分成几个小函数,让它们各自做1件事情。

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

    字母表的子组件

    在App.vue的模板中,需要定义一个&lt;alphabet&gt;子组件。该组件仅负责渲染特定字母表以及与该字母表相关的序列。

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

    您需要将字母表和相应的命中值传递给子组件才能正确渲染组件。这个子组件的代码应该是直截了当的,所以我将在这里跳过。执行此部分时,您可能需要知道如何从official documentaion 传递和使用props

    运行应用程序

    当你设置好所有函数和子组件后,你应该可以在触发renderAnswer()时渲染dad的case。

    重置状态

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

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

    结论

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

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

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

    【讨论】:

      猜你喜欢
      • 2021-10-07
      • 2017-01-03
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 1970-01-01
      • 1970-01-01
      • 2018-11-24
      • 2021-04-16
      相关资源
      最近更新 更多