跳到主要内容

第 9 节:知识点总结与避坑指南

📚 本节目标

  • 系统回顾前 8 节的核心知识点
  • 提供 Vue 3 核心语法速查表
  • 总结新手常见错误及解决方案
  • 分享调试技巧和最佳实践

一、Vue 3 核心语法速查表

1. 创建应用

// 引入 Vue
const { createApp } = Vue;

// 创建应用
const app = createApp({
data() {
return {
message: 'Hello Vue!'
}
}
});

// 挂载应用
app.mount('#app');

2. 模板语法

语法作用示例
{{ }}插值表达式<p>{{ message }}</p>
v-text设置文本内容<p v-text="message"></p>
v-html设置 HTML 内容<div v-html="htmlContent"></div>
v-bind:绑定属性<img :src="imageUrl">
v-model双向绑定<input v-model="name">
v-on@绑定事件<button @click="handleClick">
v-if条件渲染<div v-if="show">...</div>
v-else条件渲染<div v-else>...</div>
v-show切换显示<div v-show="isVisible">
v-for列表渲染<li v-for="item in list" :key="item.id">

3. 常用选项

createApp({
// 数据
data() {
return {
count: 0,
message: 'Hello'
}
},

// 计算属性
computed: {
doubleCount() {
return this.count * 2;
}
},

// 方法
methods: {
increment() {
this.count++;
}
},

// 生命周期钩子
created() {
console.log('组件已创建');
},

mounted() {
console.log('组件已挂载');
}
})

4. 事件修饰符

修饰符作用示例
.prevent阻止默认行为@submit.prevent="onSubmit"
.stop阻止事件冒泡@click.stop="handleClick"
.once只触发一次@click.once="showMessage"
.enter按下 Enter 键@keyup.enter="submit"
.esc按下 Esc 键@keyup.esc="close"

5. 组件基础

// 定义组件
app.component('my-component', {
props: ['title', 'content'],

data() {
return {
count: 0
}
},

methods: {
increment() {
this.count++;
}
},

template: `
<div>
<h3>{{ title }}</h3>
<p>{{ content }}</p>
<button @click="increment">{{ count }}</button>
</div>
`
});

// 使用组件
<my-component title="标题" content="内容"></my-component>

二、新手常见错误及解决方案

❌ 错误 1:忘记在 data 中声明数据

错误代码

createApp({
mounted() {
this.message = 'Hello'; // ❌ 没有在 data 中声明
}
}).mount('#app');

正确代码

createApp({
data() {
return {
message: '' // ✅ 先在 data 中声明
}
},
mounted() {
this.message = 'Hello';
}
}).mount('#app');

原因:Vue 的响应式系统需要在 data 中声明的数据才能追踪变化。


❌ 错误 2:data 不是函数

错误代码

createApp({
data: { // ❌ data 是对象
count: 0
}
}).mount('#app');

正确代码

createApp({
data() { // ✅ data 是函数
return {
count: 0
}
}
}).mount('#app');

原因:data 必须是函数,以确保每个组件实例都有独立的数据副本。


❌ 错误 3:在属性中使用插值表达式

错误代码

<!-- ❌ 属性中不能用 {{ }} -->
<img src="{{ imageUrl }}">

正确代码

<!-- ✅ 属性中用 v-bind 或 : -->
<img :src="imageUrl">

记住{{ }} 只能用在标签内容中,不能用在属性中!


❌ 错误 4:v-for 没有添加 key

错误代码

<!-- ❌ 没有 key -->
<li v-for="item in items">{{ item }}</li>

正确代码

<!-- ✅ 添加唯一的 key -->
<li v-for="item in items" :key="item.id">{{ item }}</li>

原因:key 帮助 Vue 识别每个元素,提高渲染效率和准确性。


❌ 错误 5:在 methods 中不使用箭头函数

错误代码

methods: {
handleClick: () => { // ❌ 箭头函数会丢失 this
this.count++; // this 指向错误
}
}

正确代码

methods: {
handleClick() { // ✅ 普通函数
this.count++;
}
}

原因:箭头函数没有自己的 this,会导致 this 指向错误。


❌ 错误 6:直接修改 props

错误代码

app.component('my-component', {
props: ['count'],
methods: {
increment() {
this.count++; // ❌ 不能直接修改 props
}
}
});

正确代码

app.component('my-component', {
props: ['count'],
data() {
return {
localCount: this.count // ✅ 复制到本地数据
}
},
methods: {
increment() {
this.localCount++;
}
}
});

原因:Props 是单向数据流,子组件不应该修改父组件传来的数据。


❌ 错误 7:v-if 和 v-for 一起使用

错误代码

<!-- ❌ v-if 和 v-for 不要在同一元素上使用 -->
<li v-for="item in items" v-if="item.visible" :key="item.id">

正确代码

<!-- ✅ 方式 1:先用 computed 过滤 -->
<li v-for="item in visibleItems" :key="item.id">

<!-- ✅ 方式 2:用 template 包裹 -->
<template v-for="item in items" :key="item.id">
<li v-if="item.visible">{{ item.text }}</li>
</template>

原因:v-for 的优先级高于 v-if,可能导致性能问题。


❌ 错误 8:忘记清理定时器

错误代码

mounted() {
setInterval(() => {
this.count++;
}, 1000);
// ❌ 组件销毁后,定时器还在运行
}

正确代码

data() {
return {
timer: null
}
},
mounted() {
this.timer = setInterval(() => {
this.count++;
}, 1000);
},
beforeUnmount() {
if (this.timer) {
clearInterval(this.timer); // ✅ 清理定时器
}
}

三、调试技巧

1. 使用 Vue Devtools

安装

  • Chrome:在扩展商店搜索 "Vue.js devtools"
  • Firefox:在附加组件中搜索 "Vue.js devtools"

功能

  • 查看组件树
  • 查看组件的 data、props、computed
  • 查看 Vuex 状态(进阶)
  • 性能分析

2. 使用 console.log 调试

methods: {
handleClick() {
console.log('点击事件触发了');
console.log('当前 count:', this.count);
console.log('完整的 data:', this.$data);
}
}

3. 在模板中调试

<!-- 临时显示数据,帮助调试 -->
<pre>{{ $data }}</pre>

<!-- 显示某个变量 -->
<p>Debug: {{ message }}</p>

4. 使用 debugger

methods: {
handleClick() {
debugger; // 代码会在这里暂停
this.count++;
}
}

四、最佳实践

1. 命名规范

// ✅ 推荐命名
data() {
return {
userName: '', // 数据:驼峰命名
isVisible: false, // 布尔值:is 开头
userList: [] // 数组:复数或 List 结尾
}
},

methods: {
handleClick() {}, // 事件处理:handle 开头
fetchData() {}, // 获取数据:fetch/get 开头
saveUser() {} // 操作:动词开头
}

2. 组件命名

// ✅ 组件名:多个单词,用短横线分隔
app.component('user-card', { ... });
app.component('todo-item', { ... });

// ❌ 避免单个单词(可能与 HTML 标签冲突)
app.component('card', { ... }); // 不推荐

3. Props 验证

// ✅ 推荐:详细的 props 验证
props: {
title: {
type: String,
required: true
},
count: {
type: Number,
default: 0
}
}

// ❌ 不推荐:简单的数组形式
props: ['title', 'count']

4. 数据结构设计

// ✅ 推荐:扁平化的数据结构
data() {
return {
userId: 1,
userName: '张三',
userAge: 18
}
}

// ❌ 不推荐:过度嵌套
data() {
return {
user: {
info: {
personal: {
name: '张三'
}
}
}
}
}

5. 方法拆分

// ✅ 推荐:一个方法做一件事
methods: {
validateForm() {
// 只负责验证
return this.name && this.email;
},

submitForm() {
// 只负责提交
if (this.validateForm()) {
// 提交逻辑
}
}
}

// ❌ 不推荐:一个方法做太多事
methods: {
submit() {
// 验证、处理、提交全在一起,不易维护
}
}

五、性能优化建议

1. 使用 v-show 代替 v-if(频繁切换的场景)

<!-- ✅ 频繁切换用 v-show -->
<div v-show="isVisible">内容</div>

<!-- ❌ 频繁切换不要用 v-if -->
<div v-if="isVisible">内容</div>

2. 避免在模板中写复杂表达式

<!-- ❌ 不推荐:模板中计算 -->
<p>{{ items.filter(item => item.visible).length }}</p>

<!-- ✅ 推荐:用 computed -->
<p>{{ visibleItemCount }}</p>

<script>
computed: {
visibleItemCount() {
return this.items.filter(item => item.visible).length;
}
}
</script>

3. 列表渲染时使用唯一的 key

<!-- ✅ 使用唯一 ID 作为 key -->
<li v-for="item in items" :key="item.id">

<!-- ❌ 使用索引作为 key(在有增删操作时) -->
<li v-for="(item, index) in items" :key="index">

六、知识点自测

问题 1:下面代码有什么问题?

<div id="app">
<img src="{{ logoUrl }}">
</div>
点击查看答案

问题:属性中不能使用插值表达式。

正确写法

<img :src="logoUrl">

问题 2:如何在页面加载完成后自动请求数据?

点击查看答案

mounted 钩子中请求数据:

mounted() {
this.fetchData();
},
methods: {
fetchData() {
// 请求数据的逻辑
}
}

问题 3:v-if 和 v-show 有什么区别?

点击查看答案
  • v-if:条件为假时,元素不会渲染到 DOM
  • v-show:条件为假时,元素仍在 DOM,只是 display: none

使用场景

  • 频繁切换 → 用 v-show
  • 不常切换 → 用 v-if

问题 4:为什么 data 必须是函数?

点击查看答案

因为组件可能被多次使用,如果 data 是对象,所有实例会共享同一个数据对象。

data 是函数时,每次调用都会返回一个新的对象,确保每个实例有独立的数据副本。


七、学习建议

1. 循序渐进

  • ✅ 先掌握基础语法,再学进阶特性
  • ✅ 每学一个知识点,动手写代码验证
  • ✅ 从简单示例到完整项目

2. 多写多练

  • ✅ 完成每节课的练习题
  • ✅ 模仿优秀的开源项目
  • ✅ 自己做一些小项目

3. 阅读官方文档

  • ✅ Vue 3 官方文档:https://cn.vuejs.org/
  • ✅ 文档是最权威、最全面的学习资料
  • ✅ 遇到问题先查文档

4. 善用开发工具

  • ✅ 安装 Vue Devtools
  • ✅ 学会使用浏览器控制台
  • ✅ 熟悉代码编辑器的快捷键

5. 保持好奇心

  • ✅ 遇到不懂的多问"为什么"
  • ✅ 尝试理解底层原理
  • ✅ 关注 Vue 社区和生态

八、本节重点回顾

核心语法:插值、指令、事件、条件、循环
常见错误:data 不是函数、属性中用插值、忘记 key 等
调试技巧:console.log、Vue Devtools、debugger
最佳实践:命名规范、Props 验证、方法拆分
性能优化:合理使用 v-show、computed、唯一 key


🎉 恭喜你完成第九节课!

到目前为止,你已经掌握了 Vue 3 的核心基础知识。接下来的最后一节,我们将探讨如何继续深入学习 Vue 生态系统。