学习 Vue.js:从零基础到入门 – wiki基地


学习 Vue.js:从零基础到入门的全面指南

在现代 Web 开发的浪潮中,前端框架扮演着至关重要的角色。它们极大地提高了开发效率、代码可维护性以及用户体验。而在众多优秀的前端框架中,Vue.js 以其平易近人的学习曲线、出色的性能和灵活的渐进式特性,赢得了全球开发者的广泛青睐。无论你是完全没有接触过前端框架的新手,还是希望扩展技术栈的开发者,Vue.js 都是一个极佳的选择。本文将带你踏上学习 Vue.js 的旅程,从最基础的概念开始,逐步深入,直至达到入门水平。

一、 为什么选择 Vue.js?

在开始学习之前,了解选择 Vue.js 的理由能让你更有动力:

  1. 易学易用 (Approachable):Vue 的核心库只关注视图层,API 设计简洁直观。官方文档清晰详尽,对新手极其友好。如果你已经掌握了 HTML、CSS 和 JavaScript 基础,那么上手 Vue 会相对轻松。
  2. 渐进式框架 (Progressive):Vue 的设计允许你逐步采用。你可以只使用其核心库来增强现有 HTML 页面,也可以将其与官方或社区提供的路由、状态管理等库结合,构建复杂的单页面应用 (SPA)。这种灵活性意味着你可以根据项目需求选择合适的工具集。
  3. 性能优异 (Performant):Vue 通过虚拟 DOM (Virtual DOM) 和精密的更新策略,最大限度地减少了实际 DOM 操作,从而保证了流畅的性能。它在体积和渲染速度方面都表现出色。
  4. 活跃的社区与生态 (Ecosystem & Community):Vue 拥有一个庞大且活跃的社区,这意味着你可以轻松找到学习资源、解决方案和第三方库。官方维护的核心库(如 Vue Router、Pinia/Vuex)质量高,生态系统完善。
  5. 中文文档友好: Vue 的作者是华人尤雨溪,官方文档提供了高质量的中文版本,这对于中文母语的学习者来说是一个巨大的优势。

二、 学习前的准备:奠定基础

虽然 Vue 致力于降低门槛,但一些基础知识是必不可少的:

  1. HTML (超文本标记语言):你需要理解 HTML 的基本结构、标签(如 <div>, <span>, <input>, <button> 等)和属性。Vue 的模板语法是基于 HTML 的。
  2. CSS (层叠样式表):了解 CSS 选择器、盒模型、布局(Flexbox/Grid)、样式规则等,用于美化 Vue 应用的界面。
  3. JavaScript (现代):这是最关键的基础。你需要掌握:
    • 基本语法:变量(var, let, const)、数据类型(字符串、数字、布尔、数组、对象等)、运算符、控制流(if/else, for, while)。
    • 函数:函数声明、函数表达式、箭头函数 (=>)。
    • DOM 操作基础:了解如何使用 JavaScript 选择和操作 HTML 元素(虽然 Vue 会帮你处理大部分 DOM 操作,但理解其原理有益)。
    • ES6+ 新特性let/const、箭头函数、模板字符串、解构赋值、模块化(import/export)等,这些在现代 Vue 开发中非常常用。
    • 异步编程:理解回调函数、Promise、async/await 的基本概念,这在处理网络请求等场景下很重要。

如果你对以上知识还不熟悉,建议先花时间巩固基础,这将使你的 Vue 学习之路更加顺畅。

三、 Vue.js 初体验:Hello, Vue!

让我们从最简单的方式开始——直接在 HTML 文件中通过 CDN 引入 Vue。

创建一个 index.html 文件,内容如下:

“`html






Hello Vue!




{{ message }}



“`

用浏览器打开这个 index.html 文件,你会看到:

  1. 页面上显示一个标题 “Hello, Vue.js!”。
  2. 标题下方有一个输入框,里面也显示着 “Hello, Vue.js!”。
  3. 尝试在输入框中修改文字,你会发现上面的标题会实时同步更新!

这就是 Vue 的魔力之一:数据绑定。我们来分解一下这段代码:

  • <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>:通过 CDN 引入了 Vue 3 的核心库。
  • <div id="app">...</div>:这是 Vue 应用的“根”元素。Vue 将控制这个 div 及其内部的所有内容。
  • <h1>{{ message }}</h1>:这被称为文本插值Mustache 语法。双大括号 {{ }} 会将 Vue 实例中 data 对象的 message 属性的值渲染到这里。
  • <input type="text" v-model="message">:这是一个带有 v-model 指令的输入框。v-model 实现了双向数据绑定。它将输入框的 value 和 Vue 实例中的 message 数据属性关联起来。当输入框的值改变时,message 会更新;反之,如果 message 在代码中被改变,输入框的值也会更新。
  • const { createApp } = Vue;:从全局 Vue 对象中解构出 createApp 函数,这是创建 Vue 3 应用的入口。
  • createApp({...}):创建了一个 Vue 应用实例。传入的对象是选项对象
  • data() { return { ... } }data 是一个函数(在组件中必须是函数,以确保每个实例有独立的数据副本),它返回一个对象,这个对象包含了应用的所有响应式状态。当这些数据变化时,Vue 会自动更新依赖这些数据的视图部分。
  • .mount('#app'):将创建的 Vue 应用实例挂载到 HTML 中 idapp 的元素上。这告诉 Vue:“请接管这个元素及其内部的内容”。

这个简单的例子展示了 Vue 的核心思想:数据驱动视图。你只需要关心数据 (message),Vue 会负责将数据的变化同步到界面上。

四、 核心概念深入:构建动态应用的基础

掌握了基本用法后,我们需要深入理解 Vue 的核心概念,它们是构建更复杂应用的基石。

1. 模板语法 (Template Syntax)

Vue 使用基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定到底层 Vue 实例的数据。

  • 文本插值: {{ expression }} – 用于在 HTML 元素内容中输出 JavaScript 表达式的值。
  • Attribute 绑定: v-bind: 或简写 : – 用于动态绑定 HTML 元素的属性。
    html
    <img :src="imageUrl">
    <button :disabled="isButtonDisabled">Click me</button>

    这里的 imageUrlisButtonDisabled 都是 Vue 实例 data 中的属性。
  • JavaScript 表达式: 在 {{ }}v-bind 中都可以使用简单的 JavaScript 表达式。
    html
    {{ number + 1 }}
    {{ message.split('').reverse().join('') }}
    <div :id="'list-' + id"></div>

2. 响应式基础 (Reactivity Fundamentals)

Vue 的核心是其响应式系统。当你把一个普通 JavaScript 对象传入 createAppdata 选项中时,Vue 会遍历其所有属性,并使用 Proxy (Vue 3) 或 Object.defineProperty (Vue 2) 将它们转换为响应式数据。

这意味着当你修改 data 中的属性时,Vue 能够侦测到这些变化,并自动重新渲染相关的 DOM 部分。

3. 计算属性 (Computed Properties)

有时我们需要基于现有的响应式数据派生出新的数据。例如,根据一个数组计算其总和,或者格式化一个日期。直接在模板中使用复杂表达式会让模板变得臃肿且难以维护。这时,计算属性就派上用场了。

javascript
createApp({
data() {
return {
firstName: 'John',
lastName: 'Doe'
}
},
computed: {
// 一个计算属性 getter
fullName() {
// `this` 指向当前 Vue 实例
console.log('Calculating full name...'); // 用于观察计算行为
return this.firstName + ' ' + this.lastName;
}
}
}).mount('#app');

在模板中使用:

“`html

Full Name: {{ fullName }}

“`

计算属性的特点:

  • 基于依赖缓存: 计算属性的值是基于它们的响应式依赖进行缓存的。只有当依赖的数据发生改变时,计算属性才会重新计算。否则,多次访问计算属性会立即返回之前的计算结果,而不会再次执行函数。这比在模板中直接写复杂表达式或在 methods 中定义一个普通函数要高效得多。
  • 声明式: 你只需要定义如何计算,Vue 会负责何时更新。

4. 侦听器 (Watchers)

虽然计算属性在大多数情况下是首选,但有时我们需要在数据变化时执行异步操作开销较大的操作。这时可以使用侦听器 (watch)

javascript
createApp({
data() {
return {
question: '',
answer: 'Questions usually contain a question mark. ;-)'
}
},
watch: {
// 每当 question 改变时,这个函数就会执行
question(newQuestion, oldQuestion) {
if (newQuestion.includes('?')) {
this.getAnswer();
}
}
},
methods: {
async getAnswer() {
this.answer = 'Thinking...';
try {
// 模拟 API 请求
const res = await fetch('https://yesno.wtf/api'); // 这是一个返回 yes/no 图片的 API
this.answer = (await res.json()).answer;
} catch (error) {
this.answer = 'Error! Could not reach the API. ' + error;
}
}
}
}).mount('#app');

在模板中:

“`html

Ask a yes/no question:

{{ answer }}

“`

watch 允许你观察一个特定的数据源,并在其变化时执行一个函数。这个函数接收新值和旧值作为参数。它非常适合执行那些响应数据变化而需要执行副作用(如 API 调用、定时器操作等)的场景。

对比 computed vs methods vs watch:

  • computed: 用于同步派生值,有缓存。适合模板中需要基于现有数据计算展示值的场景。
  • methods: 用于定义普通方法,每次调用都会执行。适合响应事件或需要显式调用的逻辑。
  • watch: 用于观察数据变化并执行异步或开销大的操作(副作用)。

5. Class 与 Style 绑定

动态地改变元素的 CSS 类名或内联样式是常见的需求。Vue 提供了 v-bind:class (简写 :class) 和 v-bind:style (简写 :style) 来处理这种情况。

“`html

“`

data 中定义相应的状态:

javascript
data() {
return {
isActive: true,
hasError: false,
activeClass: 'active',
errorClass: 'text-danger',
activeColor: 'red',
fontSize: 16,
styleObject: {
color: 'blue',
fontWeight: 'bold'
}
}
}

Vue 允许你使用对象语法或数组语法来绑定类名和样式,非常灵活。

6. 条件渲染 (Conditional Rendering)

  • v-if, v-else, v-else-if: 根据表达式的真假值来决定是否渲染一个元素或一组元素。v-if 是“惰性的”,如果条件为假,元素及其子组件根本不会被渲染(DOM 中不存在)。当条件从假变为真时,元素才会被创建和插入。
    html
    <div v-if="type === 'A'">Type A Content</div>
    <div v-else-if="type === 'B'">Type B Content</div>
    <div v-else>Other Type Content</div>
  • v-show: 根据表达式的真假值来切换元素的 CSS display 属性。无论初始条件是什么,带有 v-show 的元素总是会被渲染到 DOM 中,只是通过 CSS 控制其显示或隐藏。v-show 不支持 v-elsev-else-if

选择 v-if 还是 v-show?

  • 如果需要频繁切换显示/隐藏状态,v-show 性能更好,因为它只是切换 CSS,开销较小。
  • 如果条件很少改变,或者初始渲染时条件为假,v-if 更合适,因为它可以避免不必要的渲染开销。

7. 列表渲染 (List Rendering)

使用 v-for 指令可以基于一个数组或对象来渲染一个列表。

  • 渲染数组:
    html
    <ul>
    <li v-for="(item, index) in items" :key="item.id">
    {{ index }} - {{ item.name }}
    </li>
    </ul>

    itemsdata 中的一个数组。v-for 的语法是 (item, index) in itemsitem 是当前迭代的元素,index 是可选的索引。
  • 渲染对象:
    html
    <ul>
    <li v-for="(value, key, index) in myObject" :key="key">
    {{ index }}. {{ key }}: {{ value }}
    </li>
    </ul>

    遍历对象时,可以访问值、键名和索引。
  • key 的重要性: 当 Vue 更新 v-for 渲染的列表时,它默认使用“就地更新”策略。为了帮助 Vue 识别每个节点的身份,从而重用和重新排序现有元素,你需要为每个列表项提供一个唯一的 key 属性 (:key="...")。通常使用列表项的唯一 ID 作为 key不使用 key 或使用 index 作为 key 在某些情况下(如列表项顺序会改变、包含状态的组件或表单输入)可能导致渲染问题或性能下降,因此强烈建议始终提供唯一的 key

8. 事件处理 (Event Handling)

使用 v-on 指令(简写 @)来监听 DOM 事件,并在事件触发时执行 JavaScript 代码。

“`html


“`

methods 选项中定义事件处理函数:

javascript
createApp({
data() {
return {
counter: 0,
name: 'Vue.js'
}
},
methods: {
greet() {
alert(`Hello ${this.name}!`);
},
say(message) {
alert(message);
},
warn(message, event) {
// event 是原生 DOM 事件对象
if (event) {
event.preventDefault(); // 阻止默认行为,比如表单提交
}
alert(message);
}
}
}).mount('#app');

  • 事件修饰符: Vue 提供了一些有用的事件修饰符,可以链式调用:
    • .stop: 阻止事件冒泡 (event.stopPropagation())。
    • .prevent: 阻止默认事件 (event.preventDefault())。
    • .capture: 使用事件捕获模式。
    • .self: 只当事件是从侦听器绑定的元素本身触发时才触发处理函数。
    • .once: 事件将只会触发一次。
    • .passive: 告诉浏览器你不想阻止事件的默认行为 (提高滚动等事件的性能)。
      html
      <form @submit.prevent="onSubmit">...</form>
      <div @click.stop="doThis">...</div>
  • 按键修饰符: 监听键盘事件时,可以使用按键修饰符:
    html
    <input @keyup.enter="submitForm">
    <input @keyup.page-down="onPageDown">
    <!-- 也可以使用按键码,但不推荐 -->
    <input @keyup.13="submitForm">

五、 组件化开发:构建可复用 UI 的利器

随着应用变得复杂,将界面拆分成独立、可复用的组件 (Components) 是至关重要的。组件是 Vue 最强大的特性之一。每个组件都有自己的模板、脚本 (逻辑) 和样式。

1. 定义和注册组件

“`javascript
const app = createApp({});

// 定义一个全局组件 ‘button-counter’
app.component(‘button-counter’, {
// props 用于接收来自父组件的数据
props: [‘initialCount’],
// 每个组件实例都有自己的 data 函数
data() {
return {
count: this.initialCount || 0
}
},
// 组件的模板
template: <button @click="count++">
You clicked me {{ count }} times.
</button>

});

app.mount(‘#app’);
“`

在父模板中使用该组件:

“`html

Using the component:



“`

  • 组件命名: 组件名建议使用多个单词,并遵循 PascalCase (大驼峰命名) 或 kebab-case (短横线分隔命名)。在 HTML 模板中使用时,通常使用 kebab-case。
  • 全局注册 vs 局部注册: 上面是全局注册,任何地方都可以使用。在大型项目中,更推荐局部注册,只在需要的地方引入和注册组件,以获得更好的打包优化。
    ``javascript
    // 在一个父组件的 <script setup> (Composition API 推荐方式) 或
    components` 选项 (Options API) 中注册
    import MyComponent from ‘./MyComponent.vue’;

    // Options API
    export default {
    components: {
    ‘my-component’: MyComponent
    }
    // …
    }

    // Composition API (

    滚动至顶部