vue js类绑定在重复元素上
Posted
技术标签:
【中文标题】vue js类绑定在重复元素上【英文标题】:vue js class binding on repetitious element 【发布时间】: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> <strong style="color: red; font-size: 10px;"> num1 </strong>
</template>
<template v-else-if = "alphabet == word.second ">
<span :class=" 'active': secondActive, alphabet"> alphabet </span> <strong style="color: red; font-size: 10px;"> num2 </strong>
</template>
<template v-else-if = "alphabet == word.third ">
<span :class=" 'active': thirdActive, alphabet"> alphabet </span> <strong style="color: red; font-size: 10px;"> num3 </strong>
</template>
<template v-else-if = "alphabet == word.forth ">
<span :class=" 'active': forthActive, alphabet"> alphabet </span> <strong style="color: red; font-size: 10px;"> num4 </strong>
</template>
<template v-else-if = "alphabet == word.fifth ">
<span :class=" 'active': forthActive, alphabet"> alphabet </span> <strong style="color: red; font-size: 10px;"> num5 </strong>
</template>
<template v-else>
<span class="alphabet"> alphabet </span>
</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>
谢谢
【问题讨论】:
【参考方案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。分而治之
把你的整个任务分成三个部分:
-
创建函数来控制应突出显示哪些字母并显示相应的顺序。
创建一个组件,仅用于显示字母表和序列,例如d(1)(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的模板中,需要定义一个<alphabet>
子组件。该组件仅负责渲染特定字母表以及与该字母表相关的序列。
<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。
结论
当您在编码方面遇到一些问题时,您可以尝试重新解决您遇到的问题。 提出正确的问题将引导您使用更好的方法解决这些问题。
另一方面,将问题分解为更小的问题并逐个解决。在这种情况下,尝试将大函数拆分为一些更小更简单的函数。并且,尝试创建一个子组件来完成渲染部分,同时将所有逻辑留给它的父组件。
希望你能解决你遇到的问题,帮助更多的孩子:)
【讨论】:
以上是关于vue js类绑定在重复元素上的主要内容,如果未能解决你的问题,请参考以下文章