第 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 生态系统。