|
1 | | -# 3.1 Vue.js 基础 |
| 1 | +# 3.1 Vue.js 基础:深入核心 |
2 | 2 |
|
3 | 3 | ## 📖 概述 |
4 | 4 |
|
5 | | -本章将带你入门 Vue.js,掌握其核心概念和基本用法,为后续前端开发和与后端 API 的对接打下坚实基础。 |
| 5 | +对于前端开发经验较少的同学,本章将是你深入 Vue.js 世界的坚实起点。我们将从 Vue 的核心思想出发,详细讲解其关键概念和现代开发方式,为你后续的学习和实践扫清障碍。 |
6 | 6 |
|
7 | | -## 🌱 Vue.js 简介 |
| 7 | +## 🌱 什么是 Vue.js? |
8 | 8 |
|
9 | | -- Vue.js 是一套用于构建用户界面的渐进式 JavaScript 框架。 |
10 | | -- 采用数据驱动和组件化开发思想,易学易用,生态丰富。 |
11 | | -- 适合单页应用(SPA)和复杂前端项目。 |
| 9 | +Vue (发音为 /vjuː/,类似于 **view**) 是一套用于构建用户界面的 **渐进式 JavaScript 框架**。 |
12 | 10 |
|
13 | | -## 🚀 快速上手 |
| 11 | +- **构建用户界面 (UI)**: Vue 的核心功能是让你能够声明式地将数据渲染到 DOM (文档对象模型)。你可以将数据和模板组合起来,当数据变化时,Vue 会智能地更新界面。 |
| 12 | +- **渐进式框架 (Progressive Framework)**: 这是 Vue 的核心理念。 |
| 13 | + 1. **易于上手**: 你可以像使用 jQuery 一样,只在现有页面的局部使用 Vue,来增强交互性。 |
| 14 | + 2. **逐步采用**: 随着项目复杂度的增加,你可以逐步引入 Vue 的路由 (Vue Router)、状态管理 (Pinia) 等功能,最终构建一个功能完善的单页应用 (SPA)。 |
| 15 | + 3. **灵活多变**: 它既可以用于小型的交互式部件,也可以驱动大型、复杂的企业级应用。 |
14 | 16 |
|
15 | | -### CDN 方式引入 |
16 | | -```html |
17 | | -<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> |
18 | | -<div id="app">{{ message }}</div> |
19 | | -<script> |
20 | | - new Vue({ |
21 | | - el: '#app', |
22 | | - data: { message: 'Hello Vue!' } |
23 | | - }) |
24 | | -</script> |
| 17 | +## 🚀 创建一个现代 Vue 项目 |
| 18 | + |
| 19 | +在现代 Vue 开发中,我们推荐使用 `Vite` 来创建和管理项目。`Vite` 是一个由 Vue 作者开发的前端构建工具,它拥有极快的冷启动速度和热更新能力,能显著提升开发体验。 |
| 20 | + |
| 21 | +```bash |
| 22 | +# 确保你已安装 Node.js 16+ |
| 23 | +# 使用以下命令创建项目 (npm 7+) |
| 24 | +npm create vue@latest |
| 25 | + |
| 26 | +# 你也可以使用 yarn 或 pnpm |
| 27 | +# yarn create vue |
| 28 | +# pnpm create vue |
25 | 29 | ``` |
26 | 30 |
|
27 | | -### 使用 Vue CLI 创建项目 |
| 31 | +在创建过程中,它会提示你选择需要的特性,如 TypeScript、Pinia、Vue Router 等。对于初学者,可以先不选择,后续再手动添加。 |
| 32 | + |
| 33 | +创建完成后,进入项目目录并启动开发服务器: |
28 | 34 | ```bash |
29 | | -npm install -g @vue/cli |
30 | | -vue create my-vue-app |
31 | | -cd my-vue-app |
32 | | -npm run serve |
| 35 | +cd <your-project-name> |
| 36 | +npm install |
| 37 | +npm run dev |
33 | 38 | ``` |
34 | 39 |
|
35 | | -## 🏗️ 核心概念 |
| 40 | +## 🏗️ Vue 3 核心概念:组合式 API (Composition API) |
36 | 41 |
|
37 | | -### 1. 数据绑定 |
38 | | -```html |
39 | | -<div id="app"> |
40 | | - <input v-model="msg"> |
41 | | - <p>{{ msg }}</p> |
42 | | -</div> |
43 | | -<script> |
44 | | -new Vue({ |
45 | | - el: '#app', |
46 | | - data: { msg: '双向绑定' } |
| 42 | +Vue 3 引入了**组合式 API**,这是一种更强大、更灵活的代码组织方式,特别适合大型项目。我们本教程将主要使用这种方式。 |
| 43 | + |
| 44 | +与之对应的是 Vue 2 中主要的**选项式 API (Options API)**。 |
| 45 | + |
| 46 | +- **选项式 API**: 代码是根据 `data`, `methods`, `computed` 等选项来组织的。当组件变大时,一个功能的逻辑代码会被拆分到多个选项中,难以维护。 |
| 47 | +- **组合式 API**: 代码是根据**逻辑功能**来组织的。你可以将同一个功能的代码(如响应式状态、方法、计算属性等)放在一起,提高了代码的可读性和可维护性。 |
| 48 | + |
| 49 | +所有组合式 API 都需要在 `<script setup>` 块中使用。这是一种简洁的语法糖。 |
| 50 | + |
| 51 | +```vue |
| 52 | +<script setup> |
| 53 | +// 在这里编写组件逻辑 |
| 54 | +import { ref } from 'vue' |
| 55 | +
|
| 56 | +const message = ref('Hello Vue 3!') |
| 57 | +</script> |
| 58 | +
|
| 59 | +<template> |
| 60 | + <h1>{{ message }}</h1> |
| 61 | +</template> |
| 62 | +``` |
| 63 | + |
| 64 | +## ✨ 响应式系统: `ref()` 与 `reactive()` |
| 65 | + |
| 66 | +Vue 的核心是其响应式系统。当你修改了 JavaScript 中的数据,界面会自动更新。Vue 3 提供了两个主要的工具来实现响应性:`ref()` 和 `reactive()`。 |
| 67 | + |
| 68 | +### 1. `ref()` |
| 69 | +`ref()` 用于创建任何类型值的响应式引用,包括基本类型 (如字符串、数字) 和对象。 |
| 70 | + |
| 71 | +- **使用**: 需要通过 `.value` 来访问和修改其值。 |
| 72 | +- **场景**: 最常用于处理单个值,如字符串、数字或布尔值。 |
| 73 | + |
| 74 | +```vue |
| 75 | +<script setup> |
| 76 | +import { ref } from 'vue' |
| 77 | +
|
| 78 | +const count = ref(0) // 创建一个响应式数字 |
| 79 | +
|
| 80 | +function increment() { |
| 81 | + count.value++ // 必须使用 .value |
| 82 | +} |
| 83 | +</script> |
| 84 | +
|
| 85 | +<template> |
| 86 | + <button @click="increment"> |
| 87 | + Count is: {{ count }} |
| 88 | + </button> |
| 89 | +</template> |
| 90 | +``` |
| 91 | +> **注意**: 在模板 (`<template>`) 中使用时,Vue 会自动"解包",你不需要写 `count.value`,可以直接写 `count`。 |
| 92 | +
|
| 93 | +### 2. `reactive()` |
| 94 | +`reactive()` **只能**用于创建响应式的**对象**或**数组**。 |
| 95 | + |
| 96 | +- **使用**: 直接像普通对象一样访问和修改属性,不需要 `.value`。 |
| 97 | +- **场景**: 最适合处理一组相关的、结构化的数据。 |
| 98 | +- **限制**: 不能直接替换整个 `reactive` 对象,否则会失去响应性。 |
| 99 | + |
| 100 | +```vue |
| 101 | +<script setup> |
| 102 | +import { reactive } from 'vue' |
| 103 | +
|
| 104 | +const state = reactive({ |
| 105 | + user: { |
| 106 | + name: '张三', |
| 107 | + age: 20 |
| 108 | + } |
47 | 109 | }) |
| 110 | +
|
| 111 | +function updateAge() { |
| 112 | + state.user.age++ |
| 113 | +} |
48 | 114 | </script> |
49 | 115 | ``` |
50 | 116 |
|
51 | | -### 2. 条件与循环 |
| 117 | +**如何选择?** |
| 118 | +- 倾向于在所有地方都使用 `ref()`,这让代码风格更统一。 |
| 119 | +- 当你有一组逻辑上紧密耦合的数据时,使用 `reactive()` 可以让代码更简洁。 |
| 120 | + |
| 121 | +## 🔄 生命周期钩子 (Lifecycle Hooks) |
| 122 | + |
| 123 | +每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤——例如,它需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。这个过程允许我们使用**生命周期钩子**函数在特定阶段运行自己的代码。 |
| 124 | + |
| 125 | +下面是几个最常用的生命周期钩子: |
| 126 | + |
| 127 | +- `onMounted`: 组件被挂载 (插入到 DOM) 后调用。常用于执行需要访问 DOM 的操作,或发起数据请求。 |
| 128 | +- `onUpdated`: 组件因为响应式状态变更而更新其 DOM 树后调用。 |
| 129 | +- `onUnmounted`: 组件被卸载 (从 DOM 中移除) 后调用。常用于清理定时器、事件监听器等。 |
| 130 | + |
| 131 | +```vue |
| 132 | +<script setup> |
| 133 | +import { ref, onMounted, onUnmounted } from 'vue' |
| 134 | +
|
| 135 | +const message = ref('Lifecycle hooks demo') |
| 136 | +
|
| 137 | +onMounted(() => { |
| 138 | + console.log('组件已挂载到 DOM!') |
| 139 | + // 在这里可以安全地访问 DOM 或请求数据 |
| 140 | +}) |
| 141 | +
|
| 142 | +onUnmounted(() => { |
| 143 | + console.log('组件即将被卸载!') |
| 144 | + // 在这里进行清理工作 |
| 145 | +}) |
| 146 | +</script> |
| 147 | +``` |
| 148 | + |
| 149 | +<img src="https://v3.cn.vuejs.org/images/lifecycle.svg" alt="Vue Lifecycle Diagram" width="800"> |
| 150 | + |
| 151 | +## 📜 模板语法详解 |
| 152 | + |
| 153 | +### 文本插值 |
| 154 | +最基本的数据绑定形式是使用"Mustache"语法 (双大括号) 的文本插值: |
52 | 155 | ```html |
53 | | -<div v-if="isShow">显示内容</div> |
54 | | -<ul> |
55 | | - <li v-for="item in list" :key="item.id">{{ item.name }}</li> |
56 | | -</ul> |
| 156 | +<span>Message: {{ msg }}</span> |
57 | 157 | ``` |
58 | 158 |
|
59 | | -### 3. 事件处理 |
| 159 | +### 属性绑定 (`v-bind`) |
| 160 | +双大括号不能在 HTML 属性 (attributes) 中使用。想要响应式地绑定一个属性,应该使用 `v-bind` 指令,通常简写为 `:`。 |
| 161 | + |
60 | 162 | ```html |
61 | | -<button @click="count++">点击 {{ count }}</button> |
| 163 | +<!-- 完整语法 --> |
| 164 | +<div v-bind:id="dynamicId"></div> |
| 165 | + |
| 166 | +<!-- 简写 --> |
| 167 | +<div :id="dynamicId"></div> |
| 168 | + |
| 169 | +<!-- 绑定布尔值 --> |
| 170 | +<button :disabled="isButtonDisabled">Button</button> |
62 | 171 | ``` |
63 | 172 |
|
64 | | -### 4. 计算属性与侦听器 |
65 | | -```js |
66 | | -computed: { |
67 | | - reversedMsg() { return this.msg.split('').reverse().join('') } |
68 | | -}, |
69 | | -watch: { |
70 | | - msg(newVal) { console.log('msg changed:', newVal) } |
71 | | -} |
| 173 | +### Class 与 Style 绑定 |
| 174 | +`v-bind` 最常见的用途之一是动态地切换元素的 class 或 style。 |
| 175 | + |
| 176 | +```html |
| 177 | +<!-- 动态切换 class --> |
| 178 | +<div :class="{ active: isActive, 'text-danger': hasError }"></div> |
| 179 | + |
| 180 | +<!-- 绑定内联样式 --> |
| 181 | +<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> |
72 | 182 | ``` |
73 | 183 |
|
74 | | -### 5. 组件化开发 |
75 | | -```js |
76 | | -Vue.component('my-item', { |
77 | | - props: ['text'], |
78 | | - template: '<li>{{ text }}</li>' |
79 | | -}) |
| 184 | +### 条件渲染 (`v-if`, `v-else-if`, `v-else`) |
| 185 | +用于根据条件来渲染或销毁元素。 |
| 186 | +```html |
| 187 | +<div v-if="type === 'A'">A</div> |
| 188 | +<div v-else-if="type === 'B'">B</div> |
| 189 | +<div v-else>Not A/B</div> |
80 | 190 | ``` |
81 | 191 |
|
82 | | -## 🛠️ 与后端 API 交互 |
| 192 | +### 列表渲染 (`v-for`) |
| 193 | +用于基于一个数组来渲染一个列表。需要提供一个 `key` 来帮助 Vue 跟踪每个节点的身份。 |
| 194 | +```html |
| 195 | +<ul> |
| 196 | + <li v-for="item in items" :key="item.id"> |
| 197 | + {{ item.text }} |
| 198 | + </li> |
| 199 | +</ul> |
| 200 | +``` |
83 | 201 |
|
84 | | -### 使用 axios |
85 | | -```bash |
86 | | -npm install axios |
| 202 | +## 🖱️ 事件处理 (`v-on`) |
| 203 | + |
| 204 | +我们可以使用 `v-on` 指令 (通常简写为 `@`) 来监听 DOM 事件。 |
| 205 | + |
| 206 | +```html |
| 207 | +<!-- 内联事件处理器 --> |
| 208 | +<button @click="count++">Add 1</button> |
| 209 | + |
| 210 | +<!-- 方法事件处理器 --> |
| 211 | +<button @click="greet">Greet</button> |
87 | 212 | ``` |
88 | | -```js |
89 | | -import axios from 'axios' |
90 | | -axios.get('/api/users').then(res => { this.users = res.data }) |
| 213 | + |
| 214 | +### 事件修饰符 |
| 215 | +Vue 提供了一些事件修饰符: |
| 216 | +- `.stop`: 阻止事件继续传播。 |
| 217 | +- `.prevent`: 阻止元素的默认行为。 |
| 218 | +- `.self`: 只当事件是从侦听器绑定的元素本身触发时才触发处理函数。 |
| 219 | + |
| 220 | +```html |
| 221 | +<!-- 阻止单击事件继续传播 --> |
| 222 | +<a @click.stop="doThis"></a> |
| 223 | + |
| 224 | +<!-- 提交事件不再重载页面 --> |
| 225 | +<form @submit.prevent="onSubmit"></form> |
91 | 226 | ``` |
92 | 227 |
|
93 | | -### 异步数据加载 |
94 | | -```js |
95 | | -created() { |
96 | | - axios.get('/api/todos').then(res => { this.todos = res.data }) |
97 | | -} |
| 228 | +## 📝 表单输入绑定 (`v-model`) |
| 229 | + |
| 230 | +`v-model` 指令可以在表单的 `<input>`、`<textarea>` 及 `<select>` 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。 |
| 231 | + |
| 232 | +```html |
| 233 | +<!-- 文本输入 --> |
| 234 | +<input v-model="text" placeholder="Edit me"> |
| 235 | +<p>Message is: {{ text }}</p> |
| 236 | + |
| 237 | +<!-- 复选框 --> |
| 238 | +<input type="checkbox" id="checkbox" v-model="checked"> |
| 239 | +<label for="checkbox">{{ checked }}</label> |
98 | 240 | ``` |
99 | 241 |
|
100 | 242 | ## 📚 学习资源 |
101 | | -- [Vue.js 官方文档](https://cn.vuejs.org/) |
102 | | -- [Vue CLI 文档](https://cli.vuejs.org/zh/) |
103 | | -- [Vue 组件化开发](https://cn.vuejs.org/v2/guide/components.html) |
| 243 | + |
| 244 | +- **[Vue.js 官方文档 (v3)](https://cn.vuejs.org/)**: 学习 Vue 最权威、最全面的资源。 |
| 245 | +- **[Vite 官方文档](https://cn.vitejs.dev/)**: 了解现代前端构建工具。 |
| 246 | +- **[Vue 官方示例](https://cn.vuejs.org/guide/examples.html)**: 官方提供的各种功能的小型示例。 |
104 | 247 |
|
105 | 248 | ## 🔍 知识检查 |
106 | | -- [ ] 理解 Vue 的数据绑定和响应式原理 |
107 | | -- [ ] 能够使用指令(v-if/v-for/v-model) |
108 | | -- [ ] 能够编写简单的组件 |
109 | | -- [ ] 能够与后端 API 交互 |
| 249 | + |
| 250 | +- [ ] 理解 Vue 的渐进式框架理念是什么? |
| 251 | +- [ ] 知道如何使用 `Vite` 创建一个 Vue 项目。 |
| 252 | +- [ ] 能够区分组合式 API 和选项式 API 的不同。 |
| 253 | +- [ ] 能够解释 `ref()` 和 `reactive()` 的区别和适用场景。 |
| 254 | +- [ ] 了解 `onMounted` 等生命周期钩子的作用。 |
| 255 | +- [ ] 熟练使用 `v-bind`, `v-if`, `v-for`, `@click`, `v-model` 等常用指令。 |
| 256 | +- [ ] 知道如何使用事件修饰符(如 `.prevent`)。 |
110 | 257 |
|
111 | 258 | --- |
112 | 259 |
|
|
0 commit comments