我是天元,立志做
1000个有趣的项目
的前端。如果你喜欢的话,请
点赞,收藏,转发
。
评论
领取父爱如山
勋章
导读:本文将学习如何使用vue创建页面及组件
如何生成10以内的加减法,可直接跳到
题目页面-src/components/MathPage.vue
为项目添加音效,可直接跳到
为点击事件添加音效
获取源码请拉到最后
背景
我可爱的女儿,现在正在幼儿园中班就读。她已经开始学习10以内的加减法了,为了帮助她学习与成长,所以我决定给她写一个练习工具。
需求分析
- 鉴于我们的用户比较低龄,所以
不适宜采用负反馈
。以往各种工具中的失败,错误都不适宜出现。 - 考虑孩子识字不多,应该加入
语音系统
。考虑个人预算不多,语音系统应该免费
。 - 每次10道题目,提供10以内的加减法计算。每次点击
错误
,给予鼓励的语音
提示。让孩子重新再思考下。
相关页面UI
分为开始界面,答题界面,以及成功页面(无失败页面)
编码部分
因为页面不多,没有使用路由的必要,所以该项目仅使用组件切换
的方式来展示效果。
新建一个vue3项目
sql
npm create vue@latest
因为不需要复杂的内容,所有选项均为否
为了界面更可爱一点,修改 src/assets/main.css
,修改#app
css
#app {
margin: 0 auto;
font-weight: normal;
background: #83d4cd;
min-height: 100vh;
}
定义状态 src/App.vue
在App.vue中定义一个页面状态来决定显示哪个页面,默认为start
页面
xml
<script setup>
import { ref } from 'vue'
import StartPage from './components/StartPage.vue'
import MathPage from './components/MathPage.vue'
import SuccessPage from './components/SuccessPage.vue'
const pageStatus = ref('start')
function onChangeStatus(status) {
pageStatus.value = status
}
</script>
<template>
<StartPage @onChangeStatus="onChangeStatus" v-if="pageStatus === 'start'" />
<MathPage @onChangeStatus="onChangeStatus" v-else-if="pageStatus === 'math'" />
<SuccessPage @onChangeStatus="onChangeStatus" v-if="pageStatus === 'success'" />
</template>
<style scoped></style>
这里定义了三个组件来展示不同的页面,同时根据pageStatus
来切换。我们也定义了一个切换pageStatus的方法,便于之后在页面中的修改。
开始页面-src/components/StartPage.vue
开始页面很简单,只需要一个简单的头图+开始按钮即可。先用ai生成一个背景图,保存在src/assets/banner.jpg
xml
<script setup>
</script>
<template>
<div class="banner">
<img src="../assets/banner.png" alt="logo" />
</div>
<div class="start-button">start</div>
</template>
<style scoped>
.banner {
img {
width: 100%;
display: block;
}
}
.start-button {
width: 80%;
height: 100px;
margin: 40px auto;
border-radius: 40px;
background-color: #ffe2a6;
display: flex;
color: orange;
justify-content: center;
align-items: center;
font-size: 32px;
font-weight: bold;
cursor: pointer;
}
</style>
效果如下
绑定点击逻辑
给start按钮一个click事件,然后emit到App.vue页面
src/components/StartPage.vue
修改如下
xml
<script setup>
import { defineEmits } from 'vue';
const emit = defineEmits(['onChangeStatus']);
const onStart = () => {
emit('onChangeStatus', 'math');
};
</script>
<template>
...
<div class="start-button" @click="onStart">start</div>
</template>
现在我们绑定了一个点击事件,点击时将修改App.vue中的status,以达到切换组件的目的。
题目页面-src/components/MathPage.vue
题目页面,需要计算10以内
的加减法,所以我们分析具体情况
因为不考虑0的情况,所以加法的结果必然为2-10
,减法的第一个数字必然也是2-10
。所以我们可以先生成一个2-10
的随机数作为结果,然后再生成一个1-第一个数字
的随机数作为第二个数。再根据加减法,调换下相关数字的顺序
即可。
在题目页面创建一个函数
csharp
function createMath() {
// 生成2-10的随机数
let result = Math.floor(Math.random() * 8) + 2
const operator = Math.random() > 0.5 ? '+' : '-'; // 生成规则
const firstNumber = Math.floor(Math.random() * (result - 1)) + 1
let secondNumber = result - firstNumber
if (operator === '+') {
return {
firstNumber,
secondNumber,
operator,
result
}
} else {
return {
firstNumber: result,
secondNumber: firstNumber,
operator,
result: secondNumber
}
}
}
}
然后我们把相关的初始化逻辑补充进去,生成10道题
并存储起来。因为题目列表在页面中是不需要渲染的,所以这里不需要通过ref
初始化。设定一个current
变量,用来存储当前显示的题目和结果。
xml
<script setup>
import { ref, onMounted, defineEmits} from 'vue'
const emit=defineEmits(['onChangeStatus'])
const mathList = []
const current = ref({})
function createMath() {
...
}
onMounted(() => {
for (let i = 0; i < 10; i++) {
mathList.push(createMath())
}
current.value = mathList.pop()
})
</script>
接下来我们要创建点击函数,当点击的结果与current
的result
相同即代表是正确的,同时从题目列表中拿一个新的题目出来。
当列表中没有新的题目,即代表已经成功闯关,切换状态到成功。
matlab
function answerClick(answer) {
if (mathList.length === 0) {
emit('onChangeStatus', 'success')
return
}
if (answer === current.value.result) {
console.log('right')
current.value = mathList.shift()
} else {
console.log('wrong')
}
}
最后书写页面及绑定answerClick
xml
<template>
<div class="math">
<div class=" box">{{ current.firstNumber }}</div>
<div class=" box">{{ current.operator }}</div>
<div class=" box">{{ current.secondNumber }}</div>
<div class=" box">=</div>
<div class=" box">?</div>
</div>
<div class="answer">
<div class="answer-button" @click="answerClick(i)" v-for="i in 10">
{{ i }}</div>
</div>
</template>
<style scoped>
.math {
display: flex;
justify-content: center;
align-items: center;
font-size: 32px;
font-weight: bold;
gap: 10px;
padding: 100px 0;
font-weight: bold;
}
.box {
width: 60px;
border-radius: 10px;
background: #ffe2a6;
line-height: 60px;
text-align: center;
color: #8ec1db;
}
.answer {
padding: 0 20px;
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 10px;
}
.answer-button {
width: 60px;
height: 60px;
border-radius: 10px;
background: #fff;
line-height: 60px;
text-align: center;
color: #80ccc6;
font-size: 24px;
font-weight: bold;
cursor: pointer;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.25);
}
</style>
页面效果如下
为点击事件添加音效
相关的音频资源,可以通过在线的文字转声音
来获取,这里不做具体介绍。相关素材建议长度为3s
。另外准备正确错误的相关图标,可以从iconfont
上下载。
导入相关资源,并在触发点击事件时执行
xml
<template>
<div class="tooptip" v-if="toolTip === 'right'">
<img src="../assets/right.png" alt="right" />
</div>
<div class="tooptip" v-if="toolTip === 'wrong'">
<img src="../assets/wrong.png" alt="wrong" />
</div>
</template>
<script setup>
...
import rightAudioSource from '../assets/right.mp3'
import wrongAudioSource from '../assets/wrong.mp3'
const toolTip = ref(null)
const rightAudio = new Audio(rightAudioSource)
const wrongAudio = new Audio(wrongAudioSource)
function changeToolTip(value) {
let audio
toolTip.value = value
if (value === 'right') {
audio = rightAudio
} else if (value === 'wrong') {
audio = wrongAudio
}
audio.play()
setTimeout(() => {
toolTip.value = null
}, 3000)
}
</script>
制作结果页 src/components/SuccessPage.vue
最后再制作最终的一个简单的结果页即可。
xml
<template>
<div class="container">
<img src="../assets/success.png" alt="right" />
</div>
<div class="restart" @click="restart">
再来一次
</div>
</template>
<script setup>
import { defineEmits, onMounted } from 'vue';
import successAudioSource from '../assets/success.mp3';
const emit = defineEmits(['onChangeStatus']);
const successAudio = new Audio(successAudioSource);
const restart = () => {
emit('onChangeStatus', 'start');
};
onMounted(() => {
successAudio.play();
});
</script>
<style scoped>
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.container img {
width: 100%;
display: block;
}
.restart {
width: 80%;
height: 100px;
margin: 40px auto;
border-radius: 40px;
background-color: #ffe2a6;
display: flex;
color: orange;
justify-content: center;
align-items: center;
font-size: 32px;
font-weight: bold;
cursor: pointer;
}
</style>
最终效果
github 地址
https://github.com/tinlee/1000-project-demo/tree/main/vue3-add-and-subtract-method-within-10
我是天元,立志做
1000个有趣的项目
的前端。如果你喜欢的话,请
点赞,收藏,转发
。
评论
领取父爱如山
勋章