Vue.js零基础入门视频课程

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Vue.js是一款轻量级前端JavaScript框架,专注于视图层,易于上手且功能强大,适合构建用户界面。本课程为“Vue.js全套视频教程”的第一讲“课程简介”,专为初学者设计,帮助掌握Vue的核心概念与基础语法。内容涵盖Vue.js介绍、安装配置、基本语法、指令使用、组件开发、生命周期钩子、响应式原理、模板语法、Vuex状态管理及实战小项目等。通过本课程学习,学员可打下扎实的Vue基础,为后续学习Vue路由、动画、服务端渲染等内容做好准备。
vue.js全套视频教程-1-1课程简介

1. Vue.js介绍与核心特性

Vue.js 是一款用于构建用户界面的渐进式 JavaScript 框架,由尤雨溪于2014年发布。它以轻量、高效、易上手著称,适用于从简单页面增强到复杂单页应用(SPA)的开发。其核心库专注于视图层,易于与其他库或项目集成。

1.1 Vue.js的基本概念

Vue.js 采用声明式编程模型,开发者无需手动操作 DOM,只需关注数据状态的变化,视图会自动更新。其核心思想是“数据驱动视图”,通过 Vue 构造函数创建实例,绑定数据对象与模板,实现响应式更新。例如:

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

上述代码中, el 指定挂载点, data 定义响应式数据,当 message 变化时,视图自动更新。

1.2 Vue.js在现代前端开发中的地位

随着前端工程化的发展,Vue.js 凭借其简洁的 API 和渐进式架构,成为主流框架之一。它在中小型项目中尤为受欢迎,也支持通过 Vue Router、Vuex、Vue CLI 等生态工具构建大型应用。相比 React 和 Angular:

  • React :更偏向于“视图层”库,灵活性高但需搭配其他工具(如 Redux、React Router)。
  • Angular :功能全面但学习曲线陡峭,适合企业级应用。
  • Vue :兼具灵活性与易用性,适合快速开发和团队协作。

1.3 Vue.js的核心特性

1.3.1 响应式数据绑定

Vue 的核心机制是响应式数据绑定,通过 Object.defineProperty(Vue 2)或 Proxy(Vue 3)实现数据监听,当数据变化时,视图自动更新。

1.3.2 组件化架构

组件是 Vue 应用的基本构建单元,支持复用、嵌套与通信。通过组件化开发,可以实现模块化、可维护的前端架构。

1.3.3 指令系统

Vue 提供一系列内置指令(如 v-if、v-for、v-on、v-model),用于操作 DOM 的行为与属性。同时也支持自定义指令,扩展模板语法。

1.3.4 模板语法

Vue 使用基于 HTML 的模板语法,允许开发者将 DOM 与 Vue 实例中的数据进行绑定。例如:

<div id="app">{{ message }}</div>

模板中的 {{ message }} 是文本插值,会自动渲染为 data 中的值。

1.4 Vue.js与其他框架对比

特性 Vue.js React Angular
学习曲线 平缓 中等 陡峭
数据绑定 双向绑定(v-model) 单向绑定 双向绑定
渐进式架构
模板语法 类HTML JSX 类HTML
社区活跃度
生态工具 Vue Router、Vuex React Router、Redux Angular CLI、Material

通过对比可以看出,Vue.js 在易用性、灵活性与生态支持方面具备显著优势,特别适合中型项目和快速开发场景。

2. Vue.js安装与环境配置

在开始使用 Vue.js 构建前端应用之前,必须正确安装并配置开发环境。这一章节将详细介绍如何引入 Vue.js、搭建本地开发环境以及运行和调试项目。通过本章内容,开发者将掌握从零开始搭建 Vue.js 项目的完整流程,并具备开发 Vue 应用所需的基本工具链。

2.1 Vue.js的引入方式

在开发 Vue 应用时,引入 Vue.js 的方式决定了项目的结构和开发方式。常见的引入方式包括 CDN 引入和通过 NPM 安装模块化引入。开发者应根据项目需求选择合适的方式。

2.1.1 CDN引入

CDN(Content Delivery Network)引入方式适合快速上手或构建小型项目,无需安装构建工具即可直接在 HTML 文件中引入 Vue.js。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue CDN 引入示例</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@3"></script>
</head>
<body>
    <div id="app">
        {{ message }}
    </div>
    <script>
        const { createApp } = Vue;

        createApp({
            data() {
                return {
                    message: 'Hello Vue via CDN!'
                };
            }
        }).mount('#app');
    </script>
</body>
</html>
代码解析
  • 第 8 行:使用 <script> 标签引入 Vue.js 的 CDN 地址。
  • 第 14 行:定义 message 数据属性,初始值为字符串 'Hello Vue via CDN!'
  • 第 15 行:通过 createApp 创建 Vue 应用实例,并使用 mount 方法将应用挂载到 #app 元素上。
  • 优点:无需本地构建工具,快速启动项目。
  • 缺点:不适用于大型项目或需要模块化开发的场景。
适用场景

适用于教学演示、原型设计、静态页面增强等小型项目。

2.1.2 NPM安装与模块化引入

对于需要模块化开发、使用构建工具(如 Webpack 或 Vite)的中大型项目,推荐使用 NPM 安装 Vue.js,并通过模块化方式引入。

安装步骤
  1. 确保已安装 Node.js 和 npm(可通过 node -v npm -v 验证)。
  2. 创建项目目录并进入:
    bash mkdir my-vue-project cd my-vue-project
  3. 初始化 npm 项目:
    bash npm init -y
  4. 安装 Vue.js:
    bash npm install vue@next
示例代码
// main.js
import { createApp } from 'vue';
import App from './App.vue';

const app = createApp(App);
app.mount('#app');
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue NPM 引入示例</title>
</head>
<body>
    <div id="app"></div>
    <script type="module" src="./main.js"></script>
</body>
</html>
<!-- App.vue -->
<template>
  <div>
    {{ message }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello Vue via NPM!'
    };
  }
};
</script>
代码解析
  • 第 1 行:使用 import 引入 Vue 的 createApp 方法。
  • 第 2 行:引入 App.vue 组件。
  • 第 4 行:创建 Vue 应用实例。
  • 第 5 行:将组件挂载到 #app 元素。
  • 第 14 行:定义模板并绑定 message 数据属性。
优势
  • 支持模块化开发,便于组件复用。
  • 可集成构建工具(如 Webpack、Vite)进行打包、压缩、热更新等。
  • 更适合大型项目或团队协作开发。

2.2 开发环境搭建

为了高效开发 Vue 应用,需要搭建一个支持热更新、调试、代码压缩等特性的开发环境。

2.2.1 Node.js与npm的安装配置

Node.js 是构建现代前端项目的基础,npm 是其默认的包管理器。

安装步骤
  1. 前往 Node.js 官网 下载并安装 LTS 版本。
  2. 安装完成后,验证安装是否成功:
    bash node -v npm -v
配置 npm 镜像(可选)

国内用户可使用淘宝镜像加速安装:

npm install -g cnpm --registry=https://registry.npmmirror.com

2.2.2 使用Vue CLI创建项目

Vue CLI 是官方提供的命令行工具,可快速生成 Vue 项目脚手架。

安装 Vue CLI
npm install -g @vue/cli
创建项目
vue create my-vue-app

选择配置项后,CLI 会自动创建项目结构。

项目目录结构
my-vue-app/
├── node_modules/
├── public/
├── src/
│   ├── assets/
│   ├── components/
│   ├── App.vue
│   └── main.js
├── package.json
└── README.md
目录说明
目录/文件 作用说明
node_modules 存放项目依赖包
public 存放静态资源,如图片、robots.txt 等
src 源码目录,包含 Vue 组件和入口文件
App.vue 根组件
main.js 入口 JavaScript 文件
package.json 包管理配置文件

2.2.3 项目结构解析与开发工具配置(如VS Code)

使用 VS Code 可以提高开发效率,推荐安装以下插件:

  • Vetur :提供 Vue 单文件组件语法高亮、智能补全、格式化等功能。
  • ESLint :用于代码规范检查。
  • Prettier :自动格式化代码。
VS Code 配置步骤
  1. 安装 VS Code:https://code.visualstudio.com/
  2. 安装插件:
    - 打开 VS Code,点击左侧扩展图标,搜索并安装 Vetur、ESLint、Prettier。
  3. 配置保存时自动格式化:
    - 打开 File > Preferences > Settings
    - 搜索 format on save ,勾选 Editor: Format On Save
示例:配置 ESLint 与 Prettier 联合使用
  1. 安装依赖:
    bash npm install eslint prettier eslint-config-prettier eslint-plugin-vue eslint-plugin-vuejs-accessibility --save-dev
  2. 创建 .eslintrc.js 文件:
    js module.exports = { root: true, env: { browser: true, es2021: true }, extends: [ 'eslint:recommended', 'plugin:vue/vue3-recommended', 'plugin:@typescript-eslint/recommended', 'prettier' ], parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, plugins: ['vue', '@typescript-eslint'], rules: { // 自定义规则 } };

2.3 运行与调试Vue项目

2.3.1 启动本地开发服务器

Vue CLI 创建的项目默认支持热更新开发服务器。

启动命令
cd my-vue-app
npm run serve

执行后,终端会输出本地开发服务器地址,例如:

App running at:
- Local:   http://localhost:8080/
- Network: http://192.168.1.5:8080/
项目运行流程图
graph TD
    A[项目目录] --> B[运行 npm run serve]
    B --> C[Webpack Dev Server 启动]
    C --> D[编译 Vue 文件]
    D --> E[生成内存中的打包文件]
    E --> F[浏览器访问本地服务器]
    F --> G[实时更新页面]

2.3.2 基本调试技巧与Chrome开发者工具使用

Chrome 开发者工具(DevTools)是调试 Vue 项目的核心工具。

常用调试功能
  1. Elements 面板 :查看和修改 DOM 结构。
  2. Console 面板 :查看 JavaScript 错误、打印日志。
  3. Sources 面板 :设置断点、单步调试代码。
  4. Network 面板 :监控网络请求、查看资源加载情况。
  5. Vue Devtools 插件 :专门用于调试 Vue 应用的状态、组件结构等。
使用 Vue Devtools 调试
  1. 安装 Vue Devtools 浏览器插件。
  2. 打开项目页面,点击 Devtools 插件图标。
  3. 在 Vue 面板中查看组件树、响应式数据、事件等信息。
示例:调试组件数据

App.vue 中添加调试代码:

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">Change Message</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Initial Message'
    };
  },
  methods: {
    changeMessage() {
      console.log('Button clicked');
      this.message = 'Message Changed!';
    }
  }
};
</script>

在浏览器中点击按钮后,可以在 Console 面板中看到 'Button clicked' 输出,验证事件是否被正确触发。

本章从 Vue.js 的引入方式讲起,逐步引导读者完成开发环境的搭建与项目运行调试。通过 CDN 和 NPM 的对比,帮助开发者根据项目需求选择合适的引入方式;通过 Vue CLI 的使用和 VS Code 的配置,构建起完整的开发环境;最后介绍了如何使用 Chrome DevTools 和 Vue Devtools 进行调试,为后续章节的组件开发与数据绑定打下坚实基础。

3. Vue实例与数据绑定

在 Vue.js 中, Vue 实例 是整个应用的基石。每个 Vue 应用都从一个 Vue 实例开始,它负责将数据绑定到 DOM,并处理用户交互与视图更新之间的关系。理解 Vue 实例的创建方式及其配置项是掌握 Vue.js 的关键一步。本章将深入讲解 Vue 实例的构成、核心配置项(如 el data methods 和生命周期钩子),并结合数据绑定机制,帮助开发者构建响应式、可交互的前端应用。

3.1 Vue实例的创建与配置

Vue 实例是 Vue.js 应用的核心对象。通过 new Vue() 创建的实例会接管一个 DOM 元素,并与数据模型建立绑定关系。理解实例的创建过程和配置选项是掌握 Vue 开发的第一步。

3.1.1 el与data选项的作用

在创建 Vue 实例时,最常用的两个配置项是 el data

  • el :指定 Vue 实例挂载的目标 DOM 元素。该元素及其子元素将被 Vue 实例接管,成为数据绑定和指令作用的范围。
  • data :用于存储 Vue 实例的数据模型。这些数据是响应式的,一旦发生变化,视图会自动更新。
new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
});

对应的 HTML:

<div id="app">
  <p>{{ message }}</p>
</div>
逻辑分析:
  1. el: '#app' :表示 Vue 实例将挂载在 id 为 app 的 DOM 元素上。
  2. data 对象中的 message 属性被绑定到视图中,使用双大括号语法 {{ message }} 进行插值。
  3. message 的值发生变化时,页面中对应的 <p> 元素内容会自动更新。
参数说明:
配置项 说明
el DOM 元素的选择器,通常是 #id tagName
data 一个对象,包含 Vue 实例中可响应的数据属性

3.1.2 methods与生命周期钩子的初步使用

除了 el data methods 和生命周期钩子函数也是 Vue 实例的重要配置项。

  • methods :定义 Vue 实例的方法,这些方法可以在模板中通过事件绑定调用。
  • 生命周期钩子(Lifecycle Hooks) :Vue 实例在创建、更新和销毁过程中会触发一系列钩子函数,开发者可以在此执行初始化、清理等操作。

示例代码:

new Vue({
  el: '#app',
  data: {
    count: 0
  },
  methods: {
    increment() {
      this.count++;
    }
  },
  created() {
    console.log('Vue instance created');
  },
  mounted() {
    console.log('Vue instance mounted to DOM');
  }
});

对应的 HTML:

<div id="app">
  <p>点击次数:{{ count }}</p>
  <button @click="increment">点击增加</button>
</div>
逻辑分析:
  1. methods 中定义了 increment 方法,当按钮被点击时, count 的值会增加。
  2. created mounted 是 Vue 实例的两个生命周期钩子:
    - created :实例创建完成后调用,此时数据已初始化,但尚未挂载 DOM。
    - mounted :实例挂载完成后调用,此时 DOM 已渲染完毕。
生命周期钩子列表:
钩子函数 触发时机
beforeCreate 实例初始化之前
created 实例创建完成后
beforeMount 挂载前
mounted 挂载完成后
beforeUpdate 数据更新前
updated 数据更新完成后
beforeUnmount 实例销毁前
unmounted 实例销毁后

3.2 数据绑定机制

Vue 的一大核心特性是 响应式数据绑定 。数据模型的变化会自动更新视图,反之亦然。Vue 使用 Object.defineProperty Proxy (Vue 3)实现数据的响应式更新。

3.2.1 单向绑定与双向绑定原理

Vue 支持两种数据绑定方式:

  • 单向绑定 :数据模型 → 视图,即数据变化自动更新视图。
  • 双向绑定 :数据模型 ↔ 视图,即数据变化更新视图,视图变化也更新数据。
单向绑定示例:
<div id="app">
  <p>{{ message }}</p>
</div>
new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue'
  }
});

此时,修改 message 的值,页面内容会自动更新。

双向绑定示例(使用 v-model ):
<div id="app">
  <input v-model="message">
  <p>输入内容:{{ message }}</p>
</div>
new Vue({
  el: '#app',
  data: {
    message: ''
  }
});
逻辑分析:
  • v-model 是 Vue 提供的语法糖,用于实现双向绑定。
  • 其本质是同时使用 :value (绑定数据到输入框)和 @input (监听输入事件更新数据)。
  • 当用户在输入框中输入内容时, message 的值会自动更新,并同步到 <p> 标签中。

3.2.2 数据响应式更新机制详解

Vue 通过 数据劫持 + 发布订阅模式 实现数据的响应式更新。

数据劫持流程图(使用 mermaid):
graph TD
    A[Vue实例创建] --> B[数据对象劫持]
    B --> C{是否为对象或数组}
    C -->|是| D[递归劫持]
    C -->|否| E[使用Object.defineProperty或Proxy]
    E --> F[设置getter/setter]
    F --> G[数据变化通知Dep]
    G --> H[通知Watcher]
    H --> I[更新视图]
响应式原理简要说明:
  1. 数据劫持 :Vue 在初始化时会对 data 中的每个属性进行处理,使用 Object.defineProperty (Vue 2)或 Proxy (Vue 3)将其转换为响应式属性。
  2. 依赖收集 :当模板中使用到某个数据时,Vue 会记录该数据的依赖关系(即哪个视图依赖于该数据)。
  3. 派发更新 :当数据发生变化时,Vue 会通知所有依赖该数据的视图进行更新。

3.3 实践:实现一个简单的数据绑定示例

为了加深对 Vue 实例和数据绑定的理解,我们来实现一个简单的示例: 用户输入内容并实时显示在页面上

3.3.1 数据驱动视图更新

在这个示例中,我们将使用 Vue 的响应式数据绑定机制,实现一个输入框与显示区域的同步更新。

<div id="app">
  <input v-model="inputText">
  <p>你输入的内容是:{{ inputText }}</p>
</div>
new Vue({
  el: '#app',
  data: {
    inputText: ''
  }
});
逻辑分析:
  1. 使用 v-model 绑定 inputText <input> 输入框。
  2. 页面中的 <p> 标签显示 inputText 的值。
  3. 当用户在输入框中输入内容时, inputText 的值会被更新,触发视图重新渲染。

3.3.2 绑定用户输入与视图同步

我们可以进一步扩展功能,比如在用户输入时对内容进行过滤或转换。

<div id="app">
  <input v-model="rawInput">
  <p>处理后的内容:{{ processedInput }}</p>
</div>
new Vue({
  el: '#app',
  data: {
    rawInput: ''
  },
  computed: {
    processedInput() {
      return this.rawInput.toUpperCase();
    }
  }
});
逻辑分析:
  1. 使用 v-model 绑定原始输入值 rawInput
  2. 定义了一个计算属性 processedInput ,将输入内容转换为大写。
  3. 当用户输入内容变化时, processedInput 会自动更新,并反映在视图中。
计算属性 vs 方法:
对比项 方法 计算属性
是否缓存结果
调用方式 方法调用(需加括号) 属性访问(无需括号)
性能 每次渲染都执行 依赖数据未变时不重复执行

总结

本章围绕 Vue 实例展开,详细讲解了 el data methods 、生命周期钩子等关键配置项的使用方式,并深入剖析了 Vue 的数据绑定机制(包括单向绑定与双向绑定)。最后通过一个实际案例演示了如何利用 Vue 的响应式系统实现数据与视图的同步更新。这些内容为后续章节中组件通信、指令系统、计算属性等高级特性的学习打下了坚实基础。

4. 指令系统(v-if、v-for、v-on、v-model等)

Vue.js 的指令系统是其核心特性之一,它提供了一种简洁而强大的方式来操作 DOM 元素。通过指令,开发者可以将数据绑定到视图中,实现条件渲染、循环渲染、事件监听、表单双向绑定等常见功能。在本章中,我们将系统性地学习 Vue 指令的分类、使用方法,以及在实际项目中的应用场景。

4.1 指令的基本概念与作用

4.1.1 什么是自定义指令

在 Vue 中,指令是一种带有 v- 前缀的特殊属性,它被用于直接操作 DOM 或响应数据变化。Vue 提供了丰富的内置指令,如 v-if v-for v-on v-model 等。除此之外,Vue 也允许开发者自定义指令,以满足特定需求。

自定义指令通常用于以下场景:

  • 直接访问 DOM 元素(如聚焦、滚动、动画)
  • 实现全局的 UI 行为(如权限控制、水印)
  • 与第三方库集成(如 jQuery 插件)

示例:创建一个自定义指令用于自动聚焦输入框

<input type="text" v-focus>
// main.js
const app = createApp(App)

app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

app.mount('#app')
代码逻辑分析:
  • v-focus 是我们自定义的指令名。
  • app.directive('focus', { ... }) 注册了该指令。
  • mounted(el) 是指令的生命周期钩子之一, el 是绑定的 DOM 元素。
  • 在页面加载后,输入框会自动获得焦点。
参数说明:
钩子函数 说明
beforeMount 在绑定元素的父组件挂载之前调用
mounted 在绑定元素的父组件挂载之后调用
beforeUpdate 在包含组件的 VNode 更新之前调用
updated 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
beforeUnmount 在指令与元素解绑之前调用(仅在 Vue 3 中)
unmounted 在指令与元素解绑之后调用

4.1.2 内置指令分类与使用场景

Vue 的内置指令可以分为以下几类:

类型 指令示例 功能说明
条件渲染 v-if , v-show 控制元素是否显示
列表渲染 v-for 遍历数组或对象生成 DOM 元素
事件绑定 v-on 监听 DOM 事件
表单绑定 v-model 实现双向数据绑定
属性绑定 v-bind : 动态绑定 HTML 属性
文本渲染 v-text , v-html 渲染文本内容或 HTML 片段
示例:使用 v-html 动态插入 HTML 内容
<div v-html="rawHtml"></div>
const app = createApp({
  data() {
    return {
      rawHtml: '<strong>这是一段富文本内容</strong>'
    }
  }
})
逻辑分析:
  • v-html 会将字符串解析为 HTML 并插入到 DOM 中。
  • 不推荐用于用户输入内容,避免 XSS 攻击。

4.2 常用指令详解

4.2.1 条件渲染:v-if、v-show

Vue 提供了两种条件渲染的方式: v-if v-show

使用示例:
<h2 v-if="isVisible">我是条件显示的内容(v-if)</h2>
<h2 v-show="isVisible">我是条件显示的内容(v-show)</h2>

<button @click="toggle">切换显示</button>
const app = createApp({
  data() {
    return {
      isVisible: true
    }
  },
  methods: {
    toggle() {
      this.isVisible = !this.isVisible
    }
  }
})
对比分析:
特性 v-if v-show
渲染方式 条件为假时不渲染,不生成 DOM 节点 始终渲染,通过 CSS 控制显示
性能 切换频繁时性能较差 切换频繁时性能较好
适用场景 条件不常变化的场景 频繁切换显示的场景
流程图对比:
graph TD
    A[v-if 条件判断] --> B{条件为真?}
    B -->|是| C[渲染 DOM]
    B -->|否| D[不渲染 DOM]
    E[v-show 条件判断] --> F{条件为真?}
    F -->|是| G[设置 display: block]
    F -->|否| H[设置 display: none]

4.2.2 列表渲染:v-for

v-for 是 Vue 中最常用的循环指令,它允许我们基于数组或对象的迭代来渲染列表。

示例:使用 v-for 渲染任务列表
<ul>
  <li v-for="task in tasks" :key="task.id">
    {{ task.name }}
  </li>
</ul>
const app = createApp({
  data() {
    return {
      tasks: [
        { id: 1, name: '学习 Vue' },
        { id: 2, name: '写博客' },
        { id: 3, name: '发布文章' }
      ]
    }
  }
})
参数说明:
参数名 说明
item 当前迭代的元素
index 当前索引(可选)
array 当前遍历的数组(可选)
注意事项:
  • 始终使用 :key 提供一个唯一标识符,帮助 Vue 优化虚拟 DOM 的 diff 算法。
  • 不要使用 index 作为 key ,除非数据顺序不会变化。

4.2.3 事件绑定:v-on

v-on 指令用于监听 DOM 事件,并在触发时执行相应的 JavaScript 行为。

示例:点击按钮触发事件
<button v-on:click="sayHello">点击我</button>
<!-- 简写 -->
<button @click="sayHello">点击我</button>
const app = createApp({
  methods: {
    sayHello() {
      alert('Hello Vue!')
    }
  }
})
参数说明:
参数名 说明
$event 事件对象,可传入方法中进行处理
修饰符 .preventDefault .stopPropagation
示例:阻止默认事件
<form @submit.prevent="handleSubmit">
  <button type="submit">提交</button>
</form>
const app = createApp({
  methods: {
    handleSubmit() {
      console.log('表单提交成功')
    }
  }
})

4.2.4 表单输入绑定:v-model

v-model 是 Vue 中实现表单输入双向绑定的核心指令。它会自动将用户输入的值同步到数据模型中。

示例:使用 v-model 绑定输入框
<input type="text" v-model="message">
<p>你输入的是:{{ message }}</p>
const app = createApp({
  data() {
    return {
      message: ''
    }
  }
})
支持的表单元素:
元素类型 支持情况
input[type=text]
input[type=checkbox]
input[type=radio]
select
textarea
高级用法: .lazy .number .trim 修饰符
<!-- 输入时不立即更新,失去焦点后更新 -->
<input v-model.lazy="message">

<!-- 自动将输入值转为数字 -->
<input v-model.number="age">

<!-- 自动去除首尾空格 -->
<input v-model.trim="username">

4.3 实战应用

4.3.1 构建动态表单验证

在实际开发中,我们常常需要对用户输入进行验证。结合 v-model v-if methods ,我们可以轻松实现一个动态表单验证系统。

示例:邮箱验证表单
<form @submit.prevent="submitForm">
  <input type="text" v-model="email" placeholder="请输入邮箱">
  <p v-if="emailError" class="error">{{ emailError }}</p>
  <button type="submit">提交</button>
</form>
const app = createApp({
  data() {
    return {
      email: '',
      emailError: ''
    }
  },
  methods: {
    submitForm() {
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/

      if (!this.email) {
        this.emailError = '邮箱不能为空'
      } else if (!emailRegex.test(this.email)) {
        this.emailError = '邮箱格式不正确'
      } else {
        this.emailError = ''
        alert('提交成功!')
      }
    }
  }
})
功能说明:
  • 使用 v-model 同步用户输入。
  • 使用 v-if 动态显示错误信息。
  • 使用正则表达式进行邮箱格式验证。

4.3.2 实现一个待办事项列表(Todo List)

示例:实现一个简单的待办事项管理功能
<div id="app">
  <input v-model="newTask" @keyup.enter="addTask" placeholder="输入任务">
  <button @click="addTask">添加</button>
  <ul>
    <li v-for="task in tasks" :key="task.id">
      <input type="checkbox" v-model="task.completed">
      <span :class="{ completed: task.completed }">{{ task.text }}</span>
      <button @click="removeTask(task)">删除</button>
    </li>
  </ul>
</div>
const app = createApp({
  data() {
    return {
      newTask: '',
      tasks: []
    }
  },
  methods: {
    addTask() {
      if (this.newTask.trim()) {
        this.tasks.push({
          id: Date.now(),
          text: this.newTask,
          completed: false
        })
        this.newTask = ''
      }
    },
    removeTask(task) {
      this.tasks = this.tasks.filter(t => t.id !== task.id)
    }
  }
})
样式建议(可选):
.completed {
  text-decoration: line-through;
  color: gray;
}
功能说明:
  • 使用 v-model 绑定输入框。
  • 使用 v-for 动态生成任务列表。
  • 使用 v-model 控制任务完成状态。
  • 实现任务添加与删除功能。

通过本章的学习,我们掌握了 Vue 指令的基本概念、常用指令的使用方式以及在实际开发中的典型应用场景。这些指令是构建交互式用户界面的基础,熟练掌握它们将大大提升 Vue 应用的开发效率和质量。在后续章节中,我们将进一步深入 Vue 的计算属性、侦听器以及组件化开发等内容,进一步提升开发能力。

5. 计算属性与侦听器

计算属性和侦听器是 Vue.js 中实现数据响应式和逻辑处理的两个核心机制。它们分别适用于不同场景下的数据处理需求: 计算属性 用于处理基于已有数据派生出的新数据,具有缓存机制,适用于高频读取但低频更新的数据; 侦听器 则更适合处理异步操作或需要执行复杂逻辑的场景,例如监听某个数据变化后进行 API 请求、深度监听对象变化等。

本章将从基本用法出发,深入剖析它们的内部机制,并结合实战案例展示其在实际项目中的应用。

5.1 计算属性的基本用法

5.1.1 与methods的区别

在 Vue 中, methods computed 都可以用于封装逻辑,但它们在执行时机和性能表现上存在显著差异。

methods 的执行时机

methods 是 Vue 实例中的方法集合,它们在每次触发响应式更新时都会重新执行。即使返回的结果没有变化,只要模板中引用了该方法,它就会被调用。

<template>
  <div>
    <p>Full Name: {{ fullName() }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    }
  },
  methods: {
    fullName() {
      return `${this.firstName} ${this.lastName}`;
    }
  }
}
</script>

在这个例子中,每当 firstName lastName 发生变化, fullName() 方法都会重新执行。

computed 的执行时机

computed 属性基于其依赖的响应式数据进行缓存。只有当依赖的数据发生变化时,它才会重新求值。

<template>
  <div>
    <p>Full Name: {{ fullName }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    }
  },
  computed: {
    fullName() {
      return `${this.firstName} ${this.lastName}`;
    }
  }
}
</script>

逻辑分析:

  • fullName 依赖于 firstName lastName
  • 当这两个属性未发生变化时,多次访问 fullName 不会重新计算,而是返回缓存值。
  • 只有当其中一个依赖项发生变化时, fullName 才会重新计算。
对比总结:
特性 methods computed
是否缓存
触发频率 每次模板更新都会执行 仅当依赖变化时才执行
适用场景 不依赖缓存、需要动态计算的逻辑 基于依赖数据的复杂派生逻辑

5.1.2 缓存机制与性能优化

Vue 的计算属性之所以高效,是因为它具备缓存机制。Vue 会追踪其依赖项,只有当依赖发生变化时才会重新计算。

缓存机制的实现原理

Vue 的响应式系统会记录 computed 属性的依赖关系。当依赖项未发生变化时,直接返回缓存结果;当依赖项变化后,重新计算并缓存新值。

性能优化示例:

假设我们有一个列表,需要根据输入框内容进行过滤:

<template>
  <div>
    <input v-model="searchQuery" placeholder="Search..." />
    <ul>
      <li v-for="item in filteredItems" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      searchQuery: '',
      items: [
        { id: 1, name: 'Apple' },
        { id: 2, name: 'Banana' },
        { id: 3, name: 'Cherry' },
        { id: 4, name: 'Date' }
      ]
    }
  },
  computed: {
    filteredItems() {
      return this.items.filter(item => {
        return item.name.toLowerCase().includes(this.searchQuery.toLowerCase());
      });
    }
  }
}
</script>

逐行逻辑分析:

  • filteredItems 是一个计算属性,依赖于 items searchQuery
  • 每次 searchQuery items 发生变化时, filteredItems 会重新计算。
  • 没有使用 methods ,避免了每次渲染都执行过滤逻辑,提升性能。
性能优化建议:
  • 尽可能将基于响应式数据的复杂逻辑封装到 computed 中。
  • 避免在 methods 中重复执行相同的逻辑。
  • 对大型数据集进行操作时,优先使用 computed

5.2 侦听器(watch)的使用

5.2.1 异步操作与复杂逻辑处理

watch 主要用于观察某个数据的变化,并在其变化时执行相应的操作。与 computed 不同, watch 更适合执行异步操作或复杂逻辑,比如发送请求、修改多个状态、处理对象或数组的变化等。

示例:监听搜索输入并发送请求
<template>
  <div>
    <input v-model="searchTerm" placeholder="Search..." />
    <p v-if="loading">Loading...</p>
    <ul v-else>
      <li v-for="result in results" :key="result.id">{{ result.name }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      searchTerm: '',
      results: [],
      loading: false
    }
  },
  watch: {
    searchTerm(newVal) {
      if (newVal.length < 2) return;

      this.loading = true;

      // 模拟异步请求
      setTimeout(() => {
        this.results = [
          { id: 1, name: 'Result 1 for ' + newVal },
          { id: 2, name: 'Result 2 for ' + newVal }
        ];
        this.loading = false;
      }, 500);
    }
  }
}
</script>

逐行逻辑分析:

  • searchTerm 变化时,触发 watch 回调。
  • 设置 loading true ,显示加载状态。
  • 使用 setTimeout 模拟网络请求,获取搜索结果。
  • 请求完成后更新 results 并关闭加载状态。
适用场景总结:
  • 处理异步操作(如 API 请求)
  • 当数据变化时需要执行副作用(如通知、日志、修改其他状态)
  • 处理对象或数组深层变化(需启用 deep 选项)

5.2.2 deep immediate 选项解析

Vue 的 watch 提供了两个高级选项: deep immediate ,用于控制监听行为。

deep: true —— 深度监听对象

默认情况下,Vue 不会监听对象内部的变化。使用 deep: true 可以开启深度监听。

watch: {
  user: {
    handler(newVal) {
      console.log('User changed:', newVal);
    },
    deep: true
  }
}

说明:

  • user 是一个对象。
  • 设置 deep: true 后,即使对象内部某个属性发生变化,也能触发监听器。
immediate: true —— 立即执行回调

immediate: true 会在 watch 初始化时立即执行一次回调。

watch: {
  searchTerm: {
    handler(newVal) {
      console.log('Current value:', newVal);
    },
    immediate: true
  }
}

说明:

  • 初始化时, searchTerm 的初始值为空字符串,也会触发一次 handler
  • 这在组件加载时需要立即执行某些逻辑时非常有用。
deep immediate 组合使用示例:
watch: {
  formData: {
    handler(newVal) {
      console.log('Form data changed:', newVal);
    },
    deep: true,
    immediate: true
  }
}

应用场景:

  • 表单数据对象监听
  • 初始化时需要根据表单数据做初始化操作
  • 数据结构复杂,需要深度监听

5.3 实战:实现动态数据处理

5.3.1 实时搜索与过滤功能

在前端开发中,实时搜索与过滤是一个常见的需求。我们可以结合 computed watch 来实现一个高性能的搜索功能。

示例:结合 computed watch 实现搜索功能
<template>
  <div>
    <input v-model="searchText" placeholder="Search items..." />
    <ul>
      <li v-for="item in filteredList" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      searchText: '',
      items: [
        { id: 1, name: 'Apple' },
        { id: 2, name: 'Banana' },
        { id: 3, name: 'Cherry' },
        { id: 4, name: 'Date' }
      ],
      filteredList: []
    }
  },
  watch: {
    searchText(newVal) {
      this.filterList(newVal);
    }
  },
  methods: {
    filterList(query) {
      this.filteredList = this.items.filter(item =>
        item.name.toLowerCase().includes(query.toLowerCase())
      );
    }
  }
}
</script>

逻辑分析:

  • 使用 watch 监听 searchText 变化。
  • watch 中调用 filterList 方法进行过滤。
  • 将结果存入 filteredList ,供模板渲染使用。
性能对比:
实现方式 是否缓存 性能表现
全部使用 computed 更优
使用 watch + methods 更灵活但需手动控制
建议:
  • 如果搜索逻辑简单,优先使用 computed
  • 如果涉及异步请求或更复杂的处理逻辑,可结合 watch 使用。

5.3.2 数据变化驱动的复杂状态更新

在一些复杂场景中,我们需要监听某个数据变化来更新多个状态,甚至触发其他组件的状态变化。

示例:监听用户角色变化,更新权限状态
<template>
  <div>
    <select v-model="userRole">
      <option value="admin">Admin</option>
      <option value="editor">Editor</option>
      <option value="viewer">Viewer</option>
    </select>
    <p v-if="canEdit">You can edit content.</p>
    <p v-if="canDelete">You can delete content.</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      userRole: 'viewer',
      canEdit: false,
      canDelete: false
    }
  },
  watch: {
    userRole(newRole) {
      this.canEdit = newRole === 'admin' || newRole === 'editor';
      this.canDelete = newRole === 'admin';
    }
  }
}
</script>

逻辑分析:

  • 使用 watch 监听 userRole 的变化。
  • 根据不同的角色设置 canEdit canDelete 权限。
  • 模板中通过 v-if 控制显示对应权限的提示。
扩展讨论:
  • 如果权限逻辑复杂,可以将其封装为一个权限服务模块。
  • 在大型项目中,建议使用 Vuex 或 Pinia 进行全局状态管理。
  • 可结合 deep 监听对象结构变化,实现更灵活的状态控制。

总结(隐含在上下文中)

本章通过从基础用法到高级特性的讲解,系统性地介绍了 Vue.js 中的 计算属性 侦听器 。计算属性适合处理依赖数据的派生逻辑,具有缓存机制,适用于高性能场景;侦听器则适用于监听数据变化并执行副作用,尤其适合处理异步任务和复杂逻辑。通过多个实战案例,我们展示了如何在实际开发中合理使用它们来提升代码的可维护性和性能表现。

下一章将继续深入 Vue 的组件化开发体系,探讨组件通信机制及其在项目中的实际应用。

6. 组件化开发与组件通信

组件化开发是Vue.js中最核心、最具优势的特性之一。它通过将UI拆分为独立、可复用的组件,极大地提升了代码的可维护性和开发效率。本章将深入探讨组件化开发的基本概念、组件创建方式、父子组件之间的数据通信机制,以及非父子组件的通信策略,帮助开发者构建更加模块化和结构清晰的Vue应用。

6.1 组件的基本概念与创建

6.1.1 什么是组件化开发

组件化开发是一种将用户界面拆分为多个独立、可复用、可组合的模块的开发方式。每个组件拥有自己的模板、逻辑和样式,可以在不同的上下文中重复使用,降低代码耦合度,提高项目可维护性。

在Vue中,组件本质上是一个带有名字的Vue实例,它可以接收输入(props),并返回输出(渲染的HTML)。

6.1.2 组件的注册与使用

Vue组件分为全局组件和局部组件。全局组件在整个应用中都可以使用,局部组件仅在注册的父组件中可用。

全局组件注册示例:

// main.js
import Vue from 'vue'
import App from './App.vue'

// 定义一个全局组件
Vue.component('my-button', {
  template: `<button @click="onClick">点击我</button>`,
  methods: {
    onClick() {
      alert('按钮被点击了!')
    }
  }
})

new Vue({
  render: h => h(App)
}).$mount('#app')

局部组件注册示例:

<!-- ParentComponent.vue -->
<template>
  <div>
    <my-button />
  </div>
</template>

<script>
import MyButton from './MyButton.vue'

export default {
  components: {
    MyButton
  }
}
</script>

通过组件注册机制,开发者可以轻松实现组件的模块化复用。

6.2 父子组件通信

6.2.1 props传递数据

在父子组件通信中,父组件通过 props 向子组件传递数据。props是子组件接收外部数据的接口,具有单向数据流的特性。

示例:父组件传递title给子组件

<!-- ParentComponent.vue -->
<template>
  <child-component :title="pageTitle" />
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: { ChildComponent },
  data() {
    return {
      pageTitle: '这是子组件的标题'
    }
  }
}
</script>
<!-- ChildComponent.vue -->
<template>
  <h1>{{ title }}</h1>
</template>

<script>
export default {
  props: ['title']
}
</script>

也可以为props指定类型、默认值等:

props: {
  title: {
    type: String,
    required: true,
    default: '默认标题'
  }
}

6.2.2 自定义事件($emit)

子组件通过自定义事件将数据传递给父组件,使用 $emit 方法触发事件并传递参数。

示例:子组件向父组件传值

<!-- ChildComponent.vue -->
<template>
  <button @click="sendToParent">发送数据</button>
</template>

<script>
export default {
  methods: {
    sendToParent() {
      this.$emit('data-sent', 'Hello Parent!')
    }
  }
}
</script>
<!-- ParentComponent.vue -->
<template>
  <child-component @data-sent="handleData" />
</template>

<script>
export default {
  methods: {
    handleData(msg) {
      console.log('接收到子组件数据:', msg)
    }
  }
}
</script>

通过props和$emit的配合,可以实现父子组件之间的双向数据流动。

6.3 非父子组件通信

6.3.1 使用事件总线(Event Bus)

当组件之间没有直接父子关系时,可以使用事件总线进行通信。事件总线是一个独立的Vue实例,用于在不同组件之间发送和监听事件。

创建事件总线:

// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()

组件A发送事件:

<!-- ComponentA.vue -->
<script>
import { EventBus } from './event-bus'

export default {
  methods: {
    sendData() {
      EventBus.$emit('message', '来自组件A的消息')
    }
  }
}
</script>

组件B监听事件:

<!-- ComponentB.vue -->
<script>
import { EventBus } from './event-bus'

export default {
  created() {
    EventBus.$on('message', (msg) => {
      console.log('接收到消息:', msg)
    })
  }
}
</script>

虽然事件总线实现简单,但在大型项目中容易导致事件混乱,建议结合Vuex使用。

6.3.2 Vuex状态管理基础

Vuex是Vue官方推荐的状态管理模式,适用于管理全局状态。它通过单一状态树、Mutations、Actions和Getters实现组件间的状态共享。

Vuex基本结构:

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment')
      }, 1000)
    }
  },
  getters: {
    doubleCount(state) {
      return state.count * 2
    }
  }
})

在组件中使用:

<template>
  <div>
    <p>当前计数:{{ count }}</p>
    <p>双倍计数:{{ doubleCount }}</p>
    <button @click="increment">增加</button>
    <button @click="incrementAsync">异步增加</button>
  </div>
</template>

<script>
import { mapState, mapActions, mapGetters } from 'vuex'

export default {
  computed: {
    ...mapState(['count']),
    ...mapGetters(['doubleCount'])
  },
  methods: {
    ...mapActions(['increment', 'incrementAsync'])
  }
}
</script>

Vuex通过集中式管理,使得组件通信更加清晰、可维护。

6.4 实战:构建可复用组件库

6.4.1 实现可配置的按钮组件

我们可以创建一个通用的按钮组件,支持传入文本、类型、禁用状态等属性。

<!-- MyButton.vue -->
<template>
  <button 
    :class="['my-button', type]" 
    :disabled="disabled"
    @click="$emit('click')"
  >
    {{ label }}
  </button>
</template>

<script>
export default {
  props: {
    label: {
      type: String,
      required: true
    },
    type: {
      type: String,
      default: 'default',
      validator: value => ['default', 'primary', 'danger'].includes(value)
    },
    disabled: {
      type: Boolean,
      default: false
    }
  }
}
</script>

<style scoped>
.my-button {
  padding: 10px 20px;
  border-radius: 4px;
  border: none;
  cursor: pointer;
  margin: 5px;
}

.my-button.default {
  background-color: #f0f0f0;
  color: #333;
}

.my-button.primary {
  background-color: #42b983;
  color: white;
}

.my-button.danger {
  background-color: #e74c3c;
  color: white;
}
</style>

使用方式:

<template>
  <my-button label="提交" type="primary" @click="handleSubmit" />
</template>

6.4.2 封装通用的表单组件

我们可以创建一个通用的表单输入组件,支持动态绑定值和事件。

<!-- MyInput.vue -->
<template>
  <div class="my-input">
    <label v-if="label">{{ label }}</label>
    <input
      :type="type"
      :value="value"
      @input="$emit('input', $event.target.value)"
      :placeholder="placeholder"
    />
  </div>
</template>

<script>
export default {
  props: {
    label: String,
    type: {
      type: String,
      default: 'text'
    },
    value: [String, Number],
    placeholder: String
  }
}
</script>

使用方式:

<template>
  <div>
    <my-input label="用户名:" v-model="username" placeholder="请输入用户名" />
    <p>当前用户名:{{ username }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      username: ''
    }
  }
}
</script>

通过上述封装,我们可以构建出一个可复用的组件库,提升开发效率和代码质量。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Vue.js是一款轻量级前端JavaScript框架,专注于视图层,易于上手且功能强大,适合构建用户界面。本课程为“Vue.js全套视频教程”的第一讲“课程简介”,专为初学者设计,帮助掌握Vue的核心概念与基础语法。内容涵盖Vue.js介绍、安装配置、基本语法、指令使用、组件开发、生命周期钩子、响应式原理、模板语法、Vuex状态管理及实战小项目等。通过本课程学习,学员可打下扎实的Vue基础,为后续学习Vue路由、动画、服务端渲染等内容做好准备。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值