vue实现打字练习功能
实现思路
在Vue中实现打字练习功能,需要构建一个包含文本显示、用户输入比对和实时反馈的交互系统。核心在于监听键盘事件、比对输入内容与目标文本,并动态更新UI。
核心代码实现
模板部分
<template>
<div class="typing-container">
<div class="target-text" ref="targetText">
<span
v-for="(char, index) in targetChars"
:key="index"
:class="{
'correct': index < currentPosition && char === userInput[index],
'incorrect': index < currentPosition && char !== userInput[index],
'current': index === currentPosition
}"
>
{{ char }}
</span>
</div>
<input
v-model="userInput"
@input="checkInput"
@keydown.delete="handleBackspace"
ref="inputField"
class="typing-input"
/>
<div v-if="showResult" class="result">
正确率: {{ accuracy }}% | 用时: {{ timeUsed }}秒
</div>
</div>
</template>
脚本部分
<script>
export default {
data() {
return {
targetText: "The quick brown fox jumps over the lazy dog",
userInput: "",
currentPosition: 0,
startTime: null,
endTime: null,
showResult: false
};
},
computed: {
targetChars() {
return this.targetText.split("");
},
accuracy() {
if (this.userInput.length === 0) return 0;
let correct = 0;
for (let i = 0; i < this.userInput.length; i++) {
if (this.userInput[i] === this.targetChars[i]) correct++;
}
return Math.round((correct / this.userInput.length) * 100);
},
timeUsed() {
if (!this.startTime) return 0;
const end = this.endTime || new Date();
return ((end - this.startTime) / 1000).toFixed(2);
}
},
methods: {
checkInput() {
if (!this.startTime) this.startTime = new Date();
if (this.userInput.length > this.targetText.length) {
this.userInput = this.userInput.slice(0, this.targetText.length);
}
this.currentPosition = this.userInput.length;
if (this.userInput === this.targetText) {
this.endTime = new Date();
this.showResult = true;
}
},
handleBackspace(e) {
if (this.userInput.length === 0) {
e.preventDefault();
}
},
focusInput() {
this.$refs.inputField.focus();
}
},
mounted() {
this.focusInput();
}
};
</script>
样式部分
<style>
.typing-container {
max-width: 800px;
margin: 0 auto;
font-family: monospace;
}
.target-text {
font-size: 24px;
line-height: 1.5;
margin-bottom: 20px;
white-space: pre-wrap;
}
.target-text span {
position: relative;
}
.target-text span.correct {
color: #4CAF50;
}
.target-text span.incorrect {
color: #F44336;
text-decoration: underline;
}
.target-text span.current {
background-color: #FFEB3B;
}
.typing-input {
width: 100%;
padding: 10px;
font-size: 16px;
opacity: 0;
position: absolute;
}
.result {
margin-top: 20px;
font-size: 18px;
}
</style>
功能扩展建议
随机文本生成
可以预置多个练习文本或连接API获取随机文本:
const sampleTexts = [
"Programming is the art of telling another human what one wants the computer to do.",
"The best way to predict the future is to invent it.",
"Debugging is twice as hard as writing the code in the first place."
];
// 在data中替换targetText初始化
targetText: sampleTexts[Math.floor(Math.random() * sampleTexts.length)]
难度分级
根据用户水平调整文本长度和复杂度:
const difficultyLevels = {
easy: "Short sentences with common words",
medium: "Longer passages with technical terms",
hard: "Complex sentences with punctuation"
};
实时数据统计
添加WPM(每分钟字数)计算:
computed: {
wpm() {
if (!this.startTime || !this.userInput) return 0;
const words = this.userInput.trim().split(/\s+/).length;
const minutes = (new Date() - this.startTime) / 60000;
return Math.round(words / minutes);
}
}
注意事项
- 使用
monospace字体保证字符对齐 - 隐藏实际输入框,通过虚拟显示提升体验
- 处理退格键防止光标位置错误
- 组件销毁时移除事件监听
- 移动端需要考虑虚拟键盘的适配问题
实现过程中可以通过添加动画效果、音效反馈等方式增强用户体验。对于高级功能,可以考虑加入用户登录保存练习记录、错题统计等功能。







