🌟 京东秒杀项目训练
目标:实现Tab栏动态渲染与高亮切换
源代码:
<!-- 京东tab栏切换导航高亮 -->
<!-- 思路1。基于数据,动态渲染tab 2.准备一个下标 记录高亮哪一个tab 3.基于小标动态切换class的类名 -->
<script setup>
import { ref } from 'vue'
//tab列表
const tabs = [
{ id:1,name: '蔡徐坤' },
{ id:2,name: '陈立农' },
{ id:3,name: '范丞丞' }
]
//当前高亮的下拉,默认是第一个小标为 0
const currentIndex = ref(0)
</script>
<template>
<div>
<ul>
<li
v-for="(item, index) in tabs"
:key="item.id"
@click="currentIndex = index">
<a
:class="{active: currentIndex === index }"
href="#"
>{{ item.name }}</a>
</li>
</ul>
</div>
</template>
<style>
*{
margin: 0;
padding: 0;
}
ul{
display:flex;
border-bottom:2px solid #e01222;
padding:0 10px;
}
li{
width:100px;
height:50px;
line-height:50px;
list-style:none;
text-align:center
}
li a{
display:block;
text-decoration:none;
font-weight:bold;
color:#333333
}
li a.active{
background-color:#e01222;
color:#fff;
}
</style>
效果展示:
训练步骤
-
数据驱动渲染
-
使用
v-for
动态渲染tabs
数组,生成多个导航标签。 -
核心代码:
<li v-for="(item, index) in tabs" :key="item.id" @click="currentIndex = index"> <a :class="{ active: currentIndex === index }">{{ item.name }}</a> </li>
-
-
动态样式绑定
-
通过
currentIndex
控制当前选中项,使用:class="{ active: 条件 }"
实现高亮效果。 -
知识点:对象语法动态绑定class,键为类名,值为布尔表达式。
-
-
事件处理
-
点击标签时更新
currentIndex
,触发样式变化。 -
核心逻辑:
<li v-for="(item, index) in tabs" :key="item.id" @click="currentIndex = index"> <a :class="{ active: currentIndex === index }">{{ item.name }}</a> </li>
-
知识点提炼
-
v-for指令:动态渲染列表,需绑定
:key
提升性能。 -
动态class:
{ active: currentIndex === index }
,条件满足时添加类名。 -
响应式数据:通过
ref
管理currentIndex
,实现数据驱动视图。
📊 进度条案例训练
目标:通过按钮控制进度条动态变化
源代码:
<!-- 进度条 -->
<script setup>
import { ref } from 'vue'
//份数
const x = ref(0)
</script>
<template>
<div>
<div class="progress">
<div
class="inner"
:style="{ width: `${(x / 4) * 100}%` }">
<span>{{ (x / 4) * 100 }}%</span>
</div>
</div>
<button @click="x = 1">设置25%</button>
<button @click="x = 2">设置50%</button>
<button @click="x = 3">设置75%</button>
<button @click="x = 4">设置100%</button>
</div>
</template>
<style>
.progress{
height: 25px;
width: 400px;
border-radius: 15px;
background-color:#272425;
border: 3px solid #272425;
box-sizing: border-box;
margin-bottom: 30px;
}
.inner {
height: 20px;
border-radius: 10px;
text-align: right;
position: relative;
background-color: #409eff;
background-size: 20px 20px;
box-sizing: border-box;
transition: all 1s;
}
.inner span{
position:absolute;
right:-25px;
bottom:-25px;
}
</style>
效果展示:
训练步骤
-
数据与计算属性
-
定义
x
表示进度份数(0-4),计算属性将x
转换为百分比宽度:<li v-for="(item, index) in tabs" :key="item.id" @click="currentIndex = index"> <a :class="{ active: currentIndex === index }">{{ item.name }}</a> </li>
-
-
动态样式绑定
-
使用
:style
绑定计算属性到进度条内层元素:<div class="inner" :style="widthStyle"></div>
-
-
按钮事件驱动
-
点击按钮更新
x
,触发进度条变化:<button @click="x = 1">25%</button> <button @click="x = 4">100%</button>
-
知识点提炼
-
计算属性:
computed
基于响应式数据生成新值,缓存特性提升性能。 -
动态style:
:style="{ width: 表达式 }"
,支持对象语法绑定行内样式。 -
响应式更新:修改
x.value
后,视图自动同步变化。
📝 成绩管理表单训练
目标:实现成绩增删、统计与本地持久化
源代码:
<!-- 做了一个小表单 -->
<script setup>
import { computed, ref } from 'vue'
// 商品列表(原始数据)
const goodsList = ref([
{ id: 1, name: '蔡徐坤', num: 1 },
{ id: 2, name: '陈立农', num: 3 },
{ id: 3, name: '徐俊大', num: 2 }
])
// 由于这⾥只有原始数据,没有直接给我们提供商品总数量
// 但是我们可以基于现有的 goodsList 计算得到总数量
// 那么推荐把总数量声明为 计算属性
const totalNum = computed(() => {
return goodsList.value.reduce((prev, item) => prev + item.num, 0)
})
</script>
<template>
<h3>礼物清单</h3>
<table>
<thead>
<tr>
<th>名字</th>
<th>数量</th>
</tr>
</thead>
<tbody>
<tr
v-for="item in goodsList"
:key="item.id">
<td>{{ item.name }}</td>
<td>{{ item.num }}</td>
</tr>
</tbody>
</table>
<p>礼物总数:{{ totalNum }} 个</p>
</template>
<style>
table {
width: 350px;
border: 1px solid #333;
}
table th,
table td {
border: 1px solid #333;
}
table td {
text-align: center;
}
</style>
效果展示:
训练步骤
-
表单双向绑定
-
使用
v-model
绑定表单输入,配合修饰符优化数据:<input v-model.trim="scoreForm.subject" /> <!-- 自动去首尾空格 --> <input v-model.number="scoreForm.score" /> <!-- 自动转数字 -->
-
-
数据增删功能
-
添加:校验数据后推入数组,清空表单:
const onAdd = () => { scoreList.value.push({ ...scoreForm, id: Date.now() }); scoreForm.subject = scoreForm.score = ""; };
-
删除:通过索引移除数据,弹窗确认:
const onAdd = () => { scoreList.value.push({ ...scoreForm, id: Date.now() }); scoreForm.subject = scoreForm.score = ""; };
-
-
统计功能
-
计算总分与平均分:
const totalScore = computed(() => scoreList.value.reduce((sum, item) => sum + item.score, 0) ); const avgScore = computed(() => scoreList.value.length ? totalScore.value / scoreList.value.length : 0 );
-
-
数据持久化
-
使用
watch
深度监听scoreList
,数据变化时存入本地存储:watch( scoreList, (newVal) => localStorage.setItem("SCORE_LIST_KEY", JSON.stringify(newVal)), { deep: true } );
-
知识点提炼
-
v-model修饰符:
.trim
(去空格)、.number
(转数字)。 -
计算属性:处理复杂逻辑(如求和、求平均),依赖变化自动更新。
-
侦听器watch:监听数据变化执行副作用(如存本地),
deep: true
可深度监听对象。 -
数据持久化:利用
localStorage
实现页面刷新不丢失数据。
🎯 总结与节奏感设计
-
京东秒杀:重点练习动态渲染 + 样式绑定,节奏明快,适合熟悉 Vue 指令。
-
进度条:通过计算属性 + 动态样式,直观感受数据驱动视图的魅力。
-
成绩表单:综合运用表单处理 + 计算属性 + 侦听器,完成完整业务逻辑,适合提升实战能力。