Vue 核心语法实战:从基础指令到组件通信,4 个任务吃透 Vue 基础
本文通过4个递进式实战任务系统讲解Vue基础语法:任务1实现待办列表(v-for/v-if/v-on);任务2开发表单组件(v-model双向绑定);任务3拆分父子组件(props/$emit通信);任务4用computed/watch优化功能。每个任务包含需求分析、代码实现与核心语法解析,帮助开发者将零散语法知识点串联成完整项目。教程涵盖指令使用、组件通信、响应式工具等核心内容,同时提供进阶优化

引言
Vue 的核心优势在于 “上手简单、功能强大”,但零散的语法知识点容易让人 “一看就会,一写就废”。真正掌握 Vue 基础,关键在于将指令、双向绑定、组件通信、响应式工具等知识点串联起来,在实战中融会贯通。
本文通过 4 个递进式实践任务,从简单的指令使用到复杂的组件拆分与通信,手把手带大家落地 Vue 基础语法:实现待办列表、开发表单组件、拆分父子组件、用 computed/watch 处理数据。每个任务都包含 “需求分析→步骤拆解→代码实现→核心解析”,兼顾基础入门与深度理解,新手能跟着敲出可运行项目,有基础的开发者能夯实底层逻辑,看完直接具备独立开发简单 Vue 应用的能力!
一、任务 1:实现待办事项列表(v-for/v-if/v-on 实战)
1.1 需求分析
核心功能:输入待办内容,点击 “添加” 按钮新增条目;每条待办可勾选完成、点击 “删除” 按钮移除;未完成的待办显示 “未完成” 标签,已完成的显示 “已完成” 并添加删除线样式。
核心语法:v-for(渲染列表)、v-if(条件显示标签)、v-on(绑定点击 / 勾选事件)。
1.2 实现步骤与代码
步骤 1:初始化项目与数据
用 Vue 3 的<script setup>语法(主流推荐),定义存储待办列表的响应式数组todoList,每个待办项包含id(唯一标识)、content(内容)、done(是否完成)。
步骤 2:实现添加功能
绑定输入框的输入值,点击 “添加” 按钮时,校验输入不为空后,往todoList中 push 新待办项(用时间戳做 id 确保唯一)。
步骤 3:实现勾选与删除功能
- 勾选框绑定待办项的
done属性(双向绑定,勾选即修改done值)。- 每个待办项添加 “删除” 按钮,点击时通过索引或 id 删除对应条目。
步骤 4:条件显示与样式优化
用v-if/v-else显示 “已完成”/“未完成” 标签,用动态类名绑定完成状态的样式。
完整代码:
<template>
<div class="todo-container">
<h2>待办事项列表</h2>
<!-- 添加待办区域 -->
<div class="add-todo">
<input
v-model="newTodo"
placeholder="请输入待办内容"
class="todo-input"
/>
<button @click="addTodo" class="add-btn">添加待办</button>
</div>
<!-- 待办列表区域 -->
<div class="todo-list">
<div
class="todo-item"
v-for="(todo, index) in todoList"
:key="todo.id" <!-- 必须加key,提升渲染性能,避免错乱 -->
>
<!-- 勾选框:绑定done属性,实现双向同步 -->
<input
type="checkbox"
v-model="todo.done"
class="todo-checkbox"
/>
<!-- 待办内容:完成后添加删除线 -->
<span :class="{ 'todo-done': todo.done }">{{ todo.content }}</span>
<!-- 状态标签:条件显示 -->
<span class="todo-tag" v-if="todo.done">已完成</span>
<span class="todo-tag todo-tag-pending" v-else>未完成</span>
<!-- 删除按钮:绑定删除事件,传索引 -->
<button @click="deleteTodo(index)" class="delete-btn">删除</button>
</div>
<!-- 空列表提示 -->
<div class="empty-tip" v-if="todoList.length === 0">暂无待办事项,添加你的第一个待办吧~</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
// 响应式数据:新待办输入值
const newTodo = ref('')
// 响应式数据:待办列表(初始空数组)
const todoList = ref([
// 测试数据(可选)
{ id: Date.now() - 1000, content: "学习Vue基础指令", done: false },
{ id: Date.now() - 2000, content: "完成实战任务", done: true }
])
// 1. 添加待办函数
const addTodo = () => {
// 校验:输入不能为空
if (!newTodo.value.trim()) {
alert("待办内容不能为空!");
return;
}
// 新增待办项
todoList.value.push({
id: Date.now(), // 时间戳作为唯一id
content: newTodo.value.trim(),
done: false // 默认未完成
});
// 清空输入框
newTodo.value = '';
}
// 2. 删除待办函数:接收索引,删除对应项
const deleteTodo = (index) => {
todoList.value.splice(index, 1);
}
</script>
<style scoped>
.todo-container {
width: 600px;
margin: 30px auto;
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
}
.add-todo {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.todo-input {
flex: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
.add-btn {
padding: 10px 20px;
background: #42b983;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.add-btn:hover {
background: #359469;
}
.todo-list {
gap: 10px;
display: flex;
flex-direction: column;
}
.todo-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
background: #f9f9f9;
border-radius: 4px;
}
.todo-checkbox {
width: 18px;
height: 18px;
cursor: pointer;
}
.todo-done {
text-decoration: line-through;
color: #999;
}
.todo-tag {
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
background: #42b983;
color: white;
margin-left: auto;
}
.todo-tag-pending {
background: #f1c40f;
color: #333;
}
.delete-btn {
padding: 6px 12px;
background: #e74c3c;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-left: 10px;
}
.delete-btn:hover {
background: #c0392b;
}
.empty-tip {
text-align: center;
padding: 20px;
color: #666;
}
</style>
1.3 核心语法解析
- v-for 与 key:
v-for="(todo, index) in todoList"遍历数组,key必须绑定唯一值(优先用 id 而非 index),Vue 通过 key 识别节点,避免更新时出现 DOM 错乱,提升渲染性能。 - v-on 事件绑定:
@click="addTodo"是v-on:click="addTodo"的简写,可传递参数(如deleteTodo(index)),支持事件修饰符(如@click.prevent阻止默认行为)。 - v-if 条件渲染:
v-if控制元素是否渲染到 DOM,v-else需紧跟v-if,适合 “显示 / 隐藏” 状态切换少的场景(频繁切换建议用v-show,通过 CSS 控制显示)。
二、任务 2:开发多功能表单组件(v-model 双向绑定全场景)
2.1 需求分析
核心功能:开发一个 “待办项添加增强表单”,包含:输入待办内容(单行输入框)、选择待办优先级(下拉框)、标记是否为紧急任务(复选框)、提交表单后将数据整合到待办列表。
核心语法:v-model 双向绑定(适配输入框、下拉框、复选框等不同表单元素)。
2.2 实现步骤与代码
步骤 1:定义表单响应式数据
用reactive定义表单对象,包含content(待办内容)、priority(优先级)、isUrgent(是否紧急)。
步骤 2:绑定不同表单元素的 v-model
- 单行输入框:直接绑定
form.content。- 下拉框:
v-model绑定选中项的value值。- 复选框:单个复选框绑定布尔值(
form.isUrgent),多个复选框绑定数组。
步骤 3:表单校验与提交
提交时校验必填项,整合表单数据到待办项,新增到todoList后重置表单。
完整代码(在原有组件基础上修改,重点展示表单部分):
<template>
<div class="todo-container">
<h2>待办事项列表(增强版)</h2>
<!-- 增强表单区域 -->
<div class="todo-form">
<div class="form-item">
<label>待办内容:</label>
<input
v-model="form.content"
placeholder="请输入待办内容"
class="todo-input"
/>
</div>
<div class="form-item">
<label>优先级:</label>
<select v-model="form.priority" class="form-select">
<option value="low">低</option>
<option value="middle" selected>中</option>
<option value="high">高</option>
</select>
</div>
<div class="form-item">
<label>
<input type="checkbox" v-model="form.isUrgent" /> 紧急任务
</label>
</div>
<button @click="submitForm" class="add-btn">添加待办</button>
</div>
<!-- 待办列表区域(沿用任务1的结构,新增优先级和紧急标记显示) -->
<div class="todo-list">
<div
class="todo-item"
v-for="(todo, index) in todoList"
:key="todo.id"
>
<input type="checkbox" v-model="todo.done" class="todo-checkbox" />
<span :class="{ 'todo-done': todo.done }">
{{ todo.content }}
<!-- 显示优先级和紧急标记 -->
<span v-if="todo.isUrgent" class="urgent-tag">🔥 紧急</span>
<span class="priority-tag">{{ getPriorityText(todo.priority) }}</span>
</span>
<span class="todo-tag" v-if="todo.done">已完成</span>
<span class="todo-tag todo-tag-pending" v-else>未完成</span>
<button @click="deleteTodo(index)" class="delete-btn">删除</button>
</div>
<div class="empty-tip" v-if="todoList.length === 0">暂无待办事项,添加你的第一个待办吧~</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
// 响应式表单数据
const form = reactive({
content: '',
priority: 'middle', // 默认中等优先级
isUrgent: false // 默认非紧急
})
// 响应式数据:待办列表
const todoList = ref([])
// 优先级文本映射(避免模板中写逻辑)
const getPriorityText = (priority) => {
const map = { low: '低优先级', middle: '中优先级', high: '高优先级' }
return map[priority]
}
// 表单提交函数
const submitForm = () => {
// 校验:待办内容不能为空
if (!form.content.trim()) {
alert("待办内容不能为空!");
return;
}
// 整合表单数据,新增待办项
todoList.value.push({
id: Date.now(),
content: form.content.trim(),
done: false,
priority: form.priority,
isUrgent: form.isUrgent
});
// 重置表单
form.content = ''
form.priority = 'middle'
form.isUrgent = false
}
// 删除待办函数(沿用任务1)
const deleteTodo = (index) => {
todoList.value.splice(index, 1);
}
</script>
<style scoped>
/* 新增表单样式,其他样式沿用任务1 */
.todo-form {
display: flex;
flex-wrap: wrap;
gap: 15px;
align-items: center;
margin-bottom: 20px;
padding: 15px;
background: #f5f5f5;
border-radius: 8px;
}
.form-item {
display: flex;
align-items: center;
gap: 8px;
}
.form-select {
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
.urgent-tag {
color: #e74c3c;
font-weight: bold;
margin-left: 8px;
}
.priority-tag {
margin-left: 8px;
padding: 2px 6px;
border-radius: 4px;
background: #e3f2fd;
color: #1976d2;
font-size: 12px;
}
</style>
2.3 核心语法解析:v-model 双向绑定原理
v-model本质是语法糖,底层通过 “value 属性 + input 事件” 实现双向绑定,不同表单元素的实现逻辑略有差异:
| 表单元素 | 底层绑定逻辑 | 示例 |
|---|---|---|
| 单行输入框 | value 属性 + input 事件 | v-model="form.content" |
| 下拉框(select) | value 属性 + change 事件 | v-model="form.priority" |
| 单个复选框 | checked 属性 + change 事件 | v-model="form.isUrgent" |
| 多个复选框 | 绑定数组,change 事件添加 / 移除 value 值 | v-model="form.tags" |
v-model 工作流程图解:

三、任务 3:拆分父子组件(props 传值 + $emit 通信)
3.1 需求分析
随着功能增加,单个组件代码越来越臃肿,需拆分:
- 父组件(TodoList):管理待办列表数据(
todoList)、表单提交、数据统计。- 子组件(TodoItem):负责单个待办项的渲染(内容、优先级、紧急标记)、勾选状态切换、删除操作。
核心目标:实现父子组件通信 —— 父传子(通过 props 传递待办项数据)、子传父(通过 $emit 触发事件,通知父组件修改数据)。
3.2 组件拆分与通信流程
通信流程图解:

3.3 实现步骤与代码
步骤 1:创建子组件 TodoItem.vue
子组件通过defineProps接收父组件传递的todo数据(包含 id、content、done 等),通过defineEmits定义要触发的事件(delete删除事件、update:done勾选状态更新事件)。
步骤 2:父组件传递数据与绑定事件
父组件在v-for中使用子组件,通过todo="todo"传递单个待办项,通过@delete="handleDelete"和@update:done="handleUpdateDone"绑定事件处理函数。
步骤 3:子组件触发事件并传递数据
子组件勾选复选框时,通过emit('update:done', newDone)通知父组件更新状态;点击删除按钮时,通过emit('delete')通知父组件删除该待办项。
子组件 TodoItem.vue 完整代码:
<template>
<div class="todo-item">
<input
type="checkbox"
:checked="todo.done"
@change="handleCheck"
class="todo-checkbox"
/>
<span :class="{ 'todo-done': todo.done }">
{{ todo.content }}
<span v-if="todo.isUrgent" class="urgent-tag">🔥 紧急</span>
<span class="priority-tag">{{ getPriorityText(todo.priority) }}</span>
</span>
<span class="todo-tag" v-if="todo.done">已完成</span>
<span class="todo-tag todo-tag-pending" v-else>未完成</span>
<button @click="handleDelete" class="delete-btn">删除</button>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue'
// 1. 接收父组件传递的props(指定类型,增强健壮性)
const props = defineProps({
todo: {
type: Object,
required: true,
// 校验props结构(可选,提升代码可靠性)
validator: (value) => {
return ['id', 'content', 'done', 'priority', 'isUrgent'].every(key => key in value)
}
}
})
// 2. 定义要触发的事件
const emit = defineEmits(['delete', 'update:done'])
// 优先级文本映射
const getPriorityText = (priority) => {
const map = { low: '低优先级', middle: '中优先级', high: '高优先级' }
return map[priority]
}
// 3. 勾选事件:触发update:done事件,传递新的done值
const handleCheck = (e) => {
const newDone = e.target.checked
emit('update:done', newDone)
}
// 4. 删除事件:触发delete事件
const handleDelete = () => {
emit('delete')
}
</script>
<style scoped>
/* 样式沿用之前的todo-item相关样式,无需重复写全局样式 */
.todo-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
background: #f9f9f9;
border-radius: 4px;
}
/* 其他样式(todo-checkbox、todo-done等)沿用父组件,或按需补充 */
</style>
父组件 TodoList.vue 完整代码(简化后,重点展示组件通信):
<template>
<div class="todo-container">
<h2>待办事项列表(组件化版)</h2>
<!-- 表单区域(沿用任务2的增强表单) -->
<div class="todo-form">
<!-- 表单内容省略,同任务2 -->
</div>
<!-- 待办列表:使用子组件TodoItem -->
<div class="todo-list">
<TodoItem
v-for="(todo, index) in todoList"
:key="todo.id"
:todo="todo" <!-- 父传子:传递单个待办项数据 -->
@delete="handleDeleteTodo(index)" <!-- 子传父:监听删除事件 -->
@update:done="handleUpdateTodoDone(index, $event)" <!-- 子传父:监听状态更新事件 -->
/>
<div class="empty-tip" v-if="todoList.length === 0">暂无待办事项,添加你的第一个待办吧~</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
// 导入子组件
import TodoItem from './TodoItem.vue'
// 表单数据(同任务2)
const form = reactive({
content: '',
priority: 'middle',
isUrgent: false
})
// 待办列表数据
const todoList = ref([])
// 表单提交函数(同任务2)
const submitForm = () => {
if (!form.content.trim()) {
alert("待办内容不能为空!");
return;
}
todoList.value.push({
id: Date.now(),
content: form.content.trim(),
done: false,
priority: form.priority,
isUrgent: form.isUrgent
});
// 重置表单
form.content = ''
form.priority = 'middle'
form.isUrgent = false
}
// 处理子组件的删除事件:接收索引,删除对应待办
const handleDeleteTodo = (index) => {
todoList.value.splice(index, 1);
}
// 处理子组件的状态更新事件:接收索引和新的done值,更新数据
const handleUpdateTodoDone = (index, newDone) => {
todoList.value[index].done = newDone;
}
</script>
<style scoped>
/* 父组件样式:表单、列表容器等,子组件样式在自身组件中 */
.todo-container {
width: 600px;
margin: 30px auto;
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
}
.todo-form {
/* 同任务2的表单样式 */
}
.todo-list {
gap: 10px;
display: flex;
flex-direction: column;
}
/* 其他样式省略,同任务2 */
</style>
3.4 核心语法解析
-
props 父传子:
- 子组件通过
defineProps定义接收的属性,可指定类型、必填项、校验规则,提升代码健壮性。 - 父组件通过
:propName="value"传递数据,props 是单向数据流(子组件不能直接修改 props,需通过事件通知父组件修改)。
- 子组件通过
-
$emit 子传父:
- 子组件通过
defineEmits定义可触发的事件,触发时用emit('eventName', data)传递数据。 - 父组件通过
@eventName="handleEvent"监听事件,通过$event接收子组件传递的数据(或在事件处理函数中接收参数)。
- 子组件通过
-
组件拆分原则:
- 单一职责:一个组件只做一件事(如 TodoItem 只负责单个待办项的渲染和交互)。
- 复用性:可独立复用的部分拆分为子组件(如后续新增待办项编辑功能,可在 TodoItem 中扩展)。
- 低耦合:父子组件通过 props 和 $emit 通信,不直接操作对方的数据。
四、任务 4:用 computed/watch 优化功能(数据统计与监听)
4.1 需求分析
在现有功能基础上,新增两个核心功能:
- 统计待办事项的 “总数量”“已完成数量”“未完成数量”,实时展示在页面上。
- 监听待办列表变化(新增、删除、状态修改),给出友好的提示(如 “新增待办成功!”“已完成数量达到 5 个,真棒~”)。
核心语法:computed(缓存派生数据,统计数量)、watch(监听数据变化,触发副作用)。
4.2 实现步骤与代码
步骤 1:用 computed 统计待办数量
定义 3 个计算属性,基于todoList派生统计数据,利用 computed 的缓存机制提升性能(依赖不变时不会重复计算)。
步骤 2:用 watch 监听数据变化
- 监听
todoList的变化(深度监听,因为todoList是数组,内部元素的属性变化需要深度监听)。- 监听
doneCount(已完成数量)的变化,当达到指定阈值时给出鼓励提示。
完整代码(在父组件 TodoList.vue 中添加,重点展示 computed 和 watch 部分):
<template>
<div class="todo-container">
<h2>待办事项列表(优化版)</h2>
<!-- 统计区域:展示computed计算的结果 -->
<div class="todo-statistics">
<span>总数量:{{ totalCount }}</span>
<span>已完成:{{ doneCount }}</span>
<span>未完成:{{ pendingCount }}</span>
</div>
<!-- 表单区域、待办列表区域(沿用之前的代码) -->
</div>
</template>
<script setup>
import { ref, reactive, computed, watch } from 'vue'
import TodoItem from './TodoItem.vue'
// 表单数据、待办列表数据(同任务3)
const form = reactive({/* ... */})
const todoList = ref([])
// 1. computed:统计待办数量(缓存派生数据)
const totalCount = computed(() => {
return todoList.value.length
})
const doneCount = computed(() => {
// 过滤出done为true的待办项,返回长度
return todoList.value.filter(todo => todo.done).length
})
const pendingCount = computed(() => {
// 未完成数量 = 总数量 - 已完成数量(复用computed结果,避免重复过滤)
return totalCount.value - doneCount.value
})
// 2. watch:监听数据变化,给出提示
// 监听todoList变化(深度监听,因为要监测数组内部元素的属性变化)
watch(
() => [...todoList.value], // 监听数组的副本,确保能检测到内部变化
(newList, oldList) => {
// 新增待办:新数组长度 > 旧数组长度
if (newList.length > oldList.length) {
alert("✅ 新增待办成功!");
}
// 删除待办:新数组长度 < 旧数组长度
else if (newList.length < oldList.length) {
alert("🗑️ 待办删除成功!");
}
// 状态修改:长度不变,内容变化
else {
const newDoneCount = newList.filter(todo => todo.done).length
const oldDoneCount = oldList.filter(todo => todo.done).length
if (newDoneCount > oldDoneCount) {
alert("🎉 完成一项待办,继续加油!");
} else if (newDoneCount < oldDoneCount) {
alert("⚠️ 待办状态已改为未完成");
}
}
},
{ deep: true } // 深度监听:监测数组内部元素的变化
)
// 监听已完成数量,达到阈值给出鼓励提示
watch(
doneCount,
(newDoneCount) => {
if (newDoneCount === 5) {
alert("🏆 已完成5个待办,效率超高!");
} else if (newDoneCount === 10) {
alert("🌟 已完成10个待办,太优秀了!");
}
}
)
// 表单提交、删除、更新状态等函数(同任务3)
const submitForm = () => {/* ... */}
const handleDeleteTodo = (index) => {/* ... */}
const handleUpdateTodoDone = (index, newDone) => {/* ... */}
</script>
<style scoped>
/* 新增统计区域样式 */
.todo-statistics {
display: flex;
gap: 20px;
margin-bottom: 15px;
padding: 10px;
background: #f0f8fb;
border-radius: 4px;
}
.todo-statistics span {
font-size: 16px;
color: #2d3748;
}
/* 其他样式沿用之前的代码 */
</style>
4.3 核心语法解析
-
computed 计算属性:
- 核心优势:缓存机制 —— 只有依赖的响应式数据(如
todoList)变化时,才会重新计算,否则直接返回缓存结果。 - 适用场景:数据统计、格式化、依赖多个数据派生新值(如
pendingCount依赖totalCount和doneCount)。 - 注意:不要在 computed 中修改响应式数据(如
todoList.value.push(...)),computed 是 “纯函数”,只负责派生数据,修改数据应放在事件处理或 watch 中。
- 核心优势:缓存机制 —— 只有依赖的响应式数据(如
-
watch 侦听器:
- 核心作用:监听响应式数据变化,执行副作用(如弹出提示、发送请求、修改其他数据)。
- 深度监听:监听数组或对象时,需开启
deep: true,才能检测到内部元素或属性的变化。 - 适用场景:数据变化时的异步操作、复杂逻辑处理、阈值提醒(如完成数量达到目标)。
-
computed vs watch 选择指南:
- 当需要 “基于现有数据生成新数据” 时,用 computed(如统计数量、格式化文本)。
- 当需要 “数据变化时执行特定逻辑” 时,用 watch(如弹出提示、发送请求、清理副作用)。
五、整体效果演示与核心语法总结
5.1 整体效果
- 表单交互:输入待办内容、选择优先级、勾选紧急标记,提交后新增待办项。
- 待办列表:展示所有待办项,支持勾选完成、删除操作,显示状态、优先级和紧急标记。
- 数据统计:实时显示总数量、已完成数量、未完成数量。
- 交互提示:新增、删除、完成待办时弹出对应提示,完成数量达标时给出鼓励。
5.2 核心语法总结
| 语法 | 核心作用 | 实战场景 |
|---|---|---|
| v-for | 遍历数组 / 对象,渲染列表 | 待办列表渲染 |
| v-if/v-else | 条件渲染元素 | 显示待办状态标签、空列表提示 |
| v-on | 绑定事件(点击、change 等) | 添加、删除、勾选待办 |
| v-model | 表单元素双向绑定 | 输入框、下拉框、复选框数据绑定 |
| props | 父子组件通信(父传子) | 父组件向子组件传递待办项数据 |
| $emit | 父子组件通信(子传父) | 子组件通知父组件删除、更新状态 |
| computed | 缓存派生数据,数据统计 / 格式化 | 待办数量统计 |
| watch | 监听数据变化,执行副作用 | 交互提示、阈值提醒 |
六、进阶思考与拓展方向
6.1 进阶功能拓展
- 本地存储:用
localStorage保存待办列表,刷新页面后数据不丢失(结合 watch 监听todoList变化,自动同步到本地存储)。 - 待办编辑:新增编辑功能,点击待办项可修改内容(子组件新增编辑状态,通过 props 和 $emit 同步数据)。
- 筛选与排序:按优先级、完成状态筛选待办项,按创建时间或优先级排序(用 computed 处理筛选和排序逻辑)。
- 分页功能:当待办项过多时,实现分页展示(新增分页组件,父子组件通信传递当前页码和每页数量)。
6.2 性能优化方向
- v-for 优化:用
key绑定唯一 id,避免使用 index 作为 key;大数据量时用虚拟列表(如 vue-virtual-scroller)。 - computed 优化:拆分复杂计算属性,避免单个 computed 函数逻辑过重。
- watch 优化:避免不必要的深度监听,可通过 “函数返回特定属性” 精准监听(如
() => todoList.value.length)。 - 组件优化:子组件使用
defineProps的shallow选项(浅监听),减少不必要的重渲染。
七、互动交流
本文通过 4 个递进式任务,将 Vue 基础语法串联成可运行的实战项目,从指令使用到组件通信,再到响应式工具优化,覆盖了 Vue 入门到进阶的核心知识点。
如果你在实践过程中遇到问题(如组件通信错乱、computed 不更新、watch 监听失效等),或者有更好的拓展思路,欢迎在评论区留言讨论!如果本文对你有帮助,别忘了点赞 + 收藏,关注我,后续会持续更新 Vue 进阶实战与原理解析~

更多推荐


所有评论(0)