引言

        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 核心语法解析

  1. v-for 与 keyv-for="(todo, index) in todoList" 遍历数组,key必须绑定唯一值(优先用 id 而非 index),Vue 通过 key 识别节点,避免更新时出现 DOM 错乱,提升渲染性能。
  2. v-on 事件绑定@click="addTodo" 是v-on:click="addTodo"的简写,可传递参数(如deleteTodo(index)),支持事件修饰符(如@click.prevent阻止默认行为)。
  3. 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 核心语法解析

  1. props 父传子

    • 子组件通过defineProps定义接收的属性,可指定类型、必填项、校验规则,提升代码健壮性。
    • 父组件通过:propName="value"传递数据,props 是单向数据流(子组件不能直接修改 props,需通过事件通知父组件修改)。
  2. $emit 子传父

    • 子组件通过defineEmits定义可触发的事件,触发时用emit('eventName', data)传递数据。
    • 父组件通过@eventName="handleEvent"监听事件,通过$event接收子组件传递的数据(或在事件处理函数中接收参数)。
  3. 组件拆分原则

    • 单一职责:一个组件只做一件事(如 TodoItem 只负责单个待办项的渲染和交互)。
    • 复用性:可独立复用的部分拆分为子组件(如后续新增待办项编辑功能,可在 TodoItem 中扩展)。
    • 低耦合:父子组件通过 props 和 $emit 通信,不直接操作对方的数据。

四、任务 4:用 computed/watch 优化功能(数据统计与监听)

4.1 需求分析

在现有功能基础上,新增两个核心功能:

  1. 统计待办事项的 “总数量”“已完成数量”“未完成数量”,实时展示在页面上。
  2. 监听待办列表变化(新增、删除、状态修改),给出友好的提示(如 “新增待办成功!”“已完成数量达到 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 核心语法解析

  1. computed 计算属性

    • 核心优势:缓存机制 —— 只有依赖的响应式数据(如todoList)变化时,才会重新计算,否则直接返回缓存结果。
    • 适用场景:数据统计、格式化、依赖多个数据派生新值(如pendingCount依赖totalCountdoneCount)。
    • 注意:不要在 computed 中修改响应式数据(如todoList.value.push(...)),computed 是 “纯函数”,只负责派生数据,修改数据应放在事件处理或 watch 中。
  2. watch 侦听器

    • 核心作用:监听响应式数据变化,执行副作用(如弹出提示、发送请求、修改其他数据)。
    • 深度监听:监听数组或对象时,需开启deep: true,才能检测到内部元素或属性的变化。
    • 适用场景:数据变化时的异步操作、复杂逻辑处理、阈值提醒(如完成数量达到目标)。
  3. computed vs watch 选择指南

    • 当需要 “基于现有数据生成新数据” 时,用 computed(如统计数量、格式化文本)。
    • 当需要 “数据变化时执行特定逻辑” 时,用 watch(如弹出提示、发送请求、清理副作用)。

五、整体效果演示与核心语法总结

5.1 整体效果

  1. 表单交互:输入待办内容、选择优先级、勾选紧急标记,提交后新增待办项。
  2. 待办列表:展示所有待办项,支持勾选完成、删除操作,显示状态、优先级和紧急标记。
  3. 数据统计:实时显示总数量、已完成数量、未完成数量。
  4. 交互提示:新增、删除、完成待办时弹出对应提示,完成数量达标时给出鼓励。

5.2 核心语法总结

语法 核心作用 实战场景
v-for 遍历数组 / 对象,渲染列表 待办列表渲染
v-if/v-else 条件渲染元素 显示待办状态标签、空列表提示
v-on 绑定事件(点击、change 等) 添加、删除、勾选待办
v-model 表单元素双向绑定 输入框、下拉框、复选框数据绑定
props 父子组件通信(父传子) 父组件向子组件传递待办项数据
$emit 父子组件通信(子传父) 子组件通知父组件删除、更新状态
computed 缓存派生数据,数据统计 / 格式化 待办数量统计
watch 监听数据变化,执行副作用 交互提示、阈值提醒

六、进阶思考与拓展方向

6.1 进阶功能拓展

  1. 本地存储:用localStorage保存待办列表,刷新页面后数据不丢失(结合 watch 监听todoList变化,自动同步到本地存储)。
  2. 待办编辑:新增编辑功能,点击待办项可修改内容(子组件新增编辑状态,通过 props 和 $emit 同步数据)。
  3. 筛选与排序:按优先级、完成状态筛选待办项,按创建时间或优先级排序(用 computed 处理筛选和排序逻辑)。
  4. 分页功能:当待办项过多时,实现分页展示(新增分页组件,父子组件通信传递当前页码和每页数量)。

6.2 性能优化方向

  1. v-for 优化:用key绑定唯一 id,避免使用 index 作为 key;大数据量时用虚拟列表(如 vue-virtual-scroller)。
  2. computed 优化:拆分复杂计算属性,避免单个 computed 函数逻辑过重。
  3. watch 优化:避免不必要的深度监听,可通过 “函数返回特定属性” 精准监听(如() => todoList.value.length)。
  4. 组件优化:子组件使用definePropsshallow选项(浅监听),减少不必要的重渲染。

七、互动交流

        本文通过 4 个递进式任务,将 Vue 基础语法串联成可运行的实战项目,从指令使用到组件通信,再到响应式工具优化,覆盖了 Vue 入门到进阶的核心知识点。

        如果你在实践过程中遇到问题(如组件通信错乱、computed 不更新、watch 监听失效等),或者有更好的拓展思路,欢迎在评论区留言讨论!如果本文对你有帮助,别忘了点赞 + 收藏,关注我,后续会持续更新 Vue 进阶实战与原理解析~

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐