当前位置: 首页 > news >正文

​​Vue 3 开发速成手册

​​Vue 3 开发速成手册

  • ​​Vue 3 开发速成手册
  • 简介
    • 关键特性
    • 适用场景
  • 一、Vue的安装与配置
  • 二、Vue的项目结构
  • 三、详细解剖Vue的第一个程序HelloWorld
    • 1. 使用CDN引入Vue.js
    • 2. 创建你的第一个Vue应用
  • 四、声明式渲染(Declarative Rendering)
    • 1. 基本声明式渲染
    • 2. 指令系统
    • 3. 计算属性
  • 五、模板语法
    • 1. 插值
      • 1.1 文本插值
      • 1.2 原始 HTML
      • 1.3 使用 JavaScript 表达式
    • 2. 指令
    • 3. 条件语句
    • 4. 循环语句
      • 4.1 单次循环
      • 4.2 嵌套循环
    • 5. 属性绑定
    • 6. 计算属性和侦听器
    • 7. 列表渲染
    • 8. 表单输入绑定
    • 9. 事件处理
      • 9.1 **事件绑定语法​​**:
      • 9.2 **为什么要阻止冒泡?**
  • 六、组件
    • 1. 组件基础
    • 2. 组件 Props
    • 3. 组件事件
    • 4. 插槽
      • 4.1 Vue 组件定义部分
      • 4.2 插槽(Slot)的工作原理
      • 4.3 最终渲染结果
    • 5. 动态组件
      • 5.1 组件定义部分
      • 5.2 Vue 应用配置
      • 5.3 模板部分
  • 七、Vue3常用指令速查表
    • 1.常用指令
    • 2.修饰符速查
      • 2.1 v-model 修饰符
      • 2.2 v-on 修饰符
      • 2.3 按键修饰符
  • 八、自定义指令
    • 1. 什么是自定义指令?
    • 2. 基本语法
      • 2.1 全局注册
      • 2.2 局部注册
    • 3. 钩子函数速查表
      • 参数说明
      • 生命周期流程图

​​Vue 3 开发速成手册

简介

       Vue.js(通常简称为 Vue)是一个用于构建用户界面的渐进式 JavaScript 框架,由尤雨溪(Evan You)于 2014 年发布。它以其简洁的 API灵活的组件化开发高效的性能,迅速成为最受欢迎的前端框架之一。

       Vue 的核心目标是帮助开发者更轻松地构建动态、交互式的 Web 应用。它既适合小型项目(如增强静态页面的交互性),也能胜任复杂的企业级单页应用(SPA)。Vue 的设计哲学强调渐进式采用,开发者可以根据需求逐步引入其功能,而不需要一开始就全面重构现有项目。

关键特性

  • 响应式数据绑定:自动同步数据与视图。
  • 组件化架构:复用 UI 和逻辑。
  • 虚拟 DOM:高效渲染更新。
  • 丰富的生态系统:路由(Vue Router)、状态管理(Pinia/Vuex)、构建工具(Vite)等。

适用场景

  • 单页应用(SPA)
  • 动态内容管理
  • 交互式仪表盘
  • 渐进式 Web 应用(PWA)

一、Vue的安装与配置

       Vue环境的搭建参考这篇博客

Vue的安装与配置: https://blog.csdn.net/R_Feynman_/article/details/150268570?spm=1001.2014.3001.5501

二、Vue的项目结构

       当你用 npm init vue@latest初始化项目后,面对生成的十几个文件夹和文件很多新手在使用 Vue 脚手架创建项目后,往往会陷入这样的困惑,下面让我们来了解一下里面生成的到底是一些什么

在这里插入图片描述

  1. ​​.vscode​​
    VS Code 编辑器配置文件夹,可能包含工作区设置或调试配置

  2. ​​node_modules​​
    node_modules目录是由 ​​npm install​​ 命令自动生成的,用于存放项目依赖的所有第三方库和工具包。

  3. ​​public​​
    存放静态资源文件(如图片、字体等),这些文件会被直接复制到构建输出目录

  4. ​​src​​
    核心源代码目录,通常包含:
    main.js(入口文件)
    App.vue(根组件)
    components/(子组件)
    assets/(项目资源)
    在这里插入图片描述

  5. ​​.gitignore​​
    Git 版本控制忽略规则文件

  6. ​​index.html​​
    项目主 HTML 文件,Vue 应用的挂载点

  7. ​​jsconfig.json​​
    JavaScript 项目配置,用于提供代码智能提示和模块解析

  8. ​​package-lock.json​​
    锁定安装时的依赖版本(由 npm 自动生成)

  9. ​​package.json​​
    项目配置文件,包含:
    项目元信息
    依赖列表
    脚本命令(如 dev/build)

  10. ​​README.md​​
    项目说明文档

  11. vite.config.js​​
    Vite 构建工具配置文件

文件/文件夹类型作用描述
.vscode文件夹VS Code 编辑器特定配置
node_modules文件夹存储所有安装的 npm 依赖包
public文件夹存放无需处理的静态资源文件
src文件夹项目核心源代码目录(组件、逻辑、资源等)
.gitignore文件指定 Git 版本控制应忽略的文件和目录
index.html文件应用的主 HTML 文件,Vue 应用的挂载点
jsconfig.json文件定义 JavaScript 项目的编译器选项
package-lock.json文件锁定依赖版本,确保安装一致性
package.json文件项目配置和依赖管理文件
README.md文件项目说明文档
vite.config.js文件Vite 构建工具的配置文件

       在我们开发的时候我们可以清空src里面的components/(子组件)和 assets/(项目资源)保留一个App.vue,这样我们就有了一个纯净的Vue项目

       接下来在App.vue里面写入如下程序,在main.js里面删除import './assets/main.css' 此时恭喜你,你的第一个vue程序就诞生了

<template><div class="hello"><h1>{{ msg }}</h1></div>
</template><script>
export default {name: "hello",data() {return {msg: "欢迎来到Vue3!",};},
};
</script>

        在运行npm run dev之后就可以见到欢迎来到Vue3!的字样

三、详细解剖Vue的第一个程序HelloWorld

       作为Vue.js的初学者,你可能听说过各种复杂的构建工具和脚手架,但在刚开始学习时,最简单直接的方式就是在HTML文件中引入Vue.js的全局文件。

1. 使用CDN引入Vue.js

  1. 使用unpkg CDN来引入Vue.js(这会引入Vue 3的最新版本):
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  1. 如果你想指定版本,可以这样写:
<script src="https://unpkg.com/vue@3.2.47/dist/vue.global.js"></script>

2. 创建你的第一个Vue应用

       在第二个<script>标签中,添加以下代码:

const { createApp } = Vue;createApp({data() {return {message: '你好,Vue!'}},template: `<div>{{ message }}</div>`
}).mount('#app');

const { createApp } = Vue;

作用:解构Vue的工厂函数

       从全局Vue对象提取createApp方法,等价于:const createApp = Vue.createApp;

特点
       Vue 3的创建方式(区别于Vue 2的new Vue()) ,工厂函数模式更灵活

createApp({...})

功能:创建应用实例

配置对象包含
       data() - 响应式数据源,template - 视图模板,其他可选选项(methods/computed等)

执行过程
       接收配置对象,初始化响应式系统,编译模板,返回未挂载的应用实例

data() {...}

核心作用:声明响应式数据

       接下来给出完整的示例

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>你好,Vue3</title></head><body><div id="app"></div><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script><script>const { createApp } = Vue;createApp({data() {return {message: "你好,Vue3!",};},template: `<div>{{ message }}</div>`,}).mount("#app");</script></body>
</html>

以下是其工作原理:

①. HTML 结构

  • <div id="app"></div> 是 Vue 应用的挂载点,Vue 会将渲染的内容插入到这个 div 中

②. Vue 引入

  • <script src="...vue.global.js"> 引入了 Vue 3 的全局构建版本,这会暴露 Vue 全局变量

③. Vue 应用创建

  • const { createApp } = Vue; 从 Vue 对象中解构出 createApp 方法
  • createApp() 创建了一个 Vue 应用实例

④. 应用配置对象

  • data() 函数返回一个包含响应式数据的对象,这里定义了 message 属性
  • template 定义了应用的模板,使用双大括号 {{ }} 语法绑定 message 数据

⑤. 挂载应用

  • .mount("#app") 将 Vue 应用挂载到 id 为 “app” 的 DOM 元素上

四、声明式渲染(Declarative Rendering)

       ​​声明式渲染​​是 Vue.js 的核心思想之一,贯穿了整个 Vue 的设计理念和开发模式。Vue 通过​​响应式数据绑定​​和​​模板语法​​,让开发者可以​​声明式​​地描述 UI 应该是什么样子,而无需手动操作 DOM

1. 基本声明式渲染

<div id="app">{{ message }}
</div>`
const app = new Vue({el: '#app',data: {message: 'Hello Vue!'}
})

在这个例子中:

• 双大括号 {{       }}是 Vue 的模板语法

message是 Vue 实例的 data 对象中的一个属性

• 当 data 中的 message改变时,视图会自动更新

2. 指令系统

Vue 提供了多种指令来实现声明式渲染:

v-bind (绑定属性)

<div v-bind:title="message">鼠标悬停查看动态绑定的标题
</div>

简写形式

<div :title="message">简写形式
</div>

v-for (列表渲染)

<ul><li v-for="item in items" :key="item.id">{{ item.text }}</li>
</ul>

3. 计算属性

对于复杂逻辑,可以使用计算属性:

new Vue({el: '#app',data: {firstName: '张',lastName: '三'},computed: {fullName: function() {return this.firstName + ' ' + this.lastName}}
})

五、模板语法

温馨提示这个框架可以把下面的任何一段代码放进来运行
下面的代码为了方便调试,全部都是在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 3 表单绑定示例</title><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body><!-- 温馨提示这个框架可以把下面的任何一段代码放进来运行 -->
</body>
</html>

1. 插值

1.1 文本插值

       使用双大括号 {{ }}(Mustache 语法)进行文本插值:

  <div id="app"><p>{{ message }}</p><button @click="change">更改</button></div><script>Vue.createApp({data() {return { message: "Hello Vue!" }},methods: {change() { this.message = "Changed!" }}}).mount('#app')</script>

1.2 原始 HTML

       双大括号会将数据解释为普通文本,使用 v-html 指令可以输出真正的 HTML:

  <div id="app"><div :class="{ active: isActive }">红色文字</div><button @click="toggle">切换</button></div><script>Vue.createApp({data() { return { isActive: true } },methods: {toggle() { this.isActive = !this.isActive }}}).mount('#app')</script>

1.3 使用 JavaScript 表达式

Vue 支持在模板中使用 JavaScript 表达式:
       1.​​基本运算​​:{{ number + 1 }}→ 显示 11
       2.​​三元表达式​​:{{ ok ? ‘YES’ : ‘NO’ }}→ 显示 YES
       3.​​方法调用​​:{{ message.split(‘’).reverse().join(‘’) }}→ 显示 “olleH”
       4.​​属性绑定中的表达式​​::id="‘list-’ + id"→ 生成 id=“list-1”

  <div id="app"><!-- 基本运算 --><p>数字加1: {{ number + 1 }}</p><!-- 三元表达式 --><p>状态判断: {{ ok ? 'YES' : 'NO' }}</p><!-- 方法调用 --><p>反转字符串: {{ message.split('').reverse().join('') }}</p><!-- 属性绑定中使用表达式 --><div :id="'list-' + id">这个div的ID是: list-{{ id }}</div><!-- 显示原始数据 --><hr><h3>当前数据状态:</h3><p>number: {{ number }}</p><p>ok: {{ ok }}</p><p>message: {{ message }}</p><p>id: {{ id }}</p></div><script>const { createApp } = Vue;createApp({data() {return {number: 10,ok: true,message: 'Hello',id: 1}}}).mount('#app');</script>

2. 指令

指令是带有 v-前缀的特殊 attribute

1.​​条件渲染 (v-if)​​:
       显示/隐藏文本
       添加了切换按钮显示当前状态

2.​​事件监听​​:
       展示了完整语法(v-on:click)和简写语法(@click)
       点击按钮会触发alert

3.动态参数​​:
       动态绑定属性名和事件名
       显示当前使用的属性名和事件名

4.表单输入绑定 (v-model)​​:
       实现输入框和数据的双向绑定
       实时显示输入内容

    <div id="app"><h2>Vue 3 指令演示</h2><!-- 条件渲染 --><div><h3>1. 条件渲染 (v-if)</h3><p v-if="seen">现在你看到我了</p><button @click="seen = !seen">切换显示状态</button><p>当前seen值: {{ seen }}</p></div><!-- 事件监听 --><div><h3>2. 事件监听</h3><button v-on:click="doSomething">点击我 (完整语法)</button><button @click="doSomething">点击我 (简写语法)</button></div><!-- 动态参数 --><div><h3>3. 动态参数</h3><a v-bind:[attributeName]="url">动态绑定href属性的链接</a><br><a @[eventName]="doSomething">动态绑定click事件的链接</a><p>当前attributeName: "{{ attributeName }}"</p><p>当前eventName: "{{ eventName }}"</p></div><!-- 表单输入绑定 --><div><h3>4. 表单输入绑定 (v-model)</h3><input v-model="message" placeholder="编辑我"><p>Message is: {{ message }}</p></div></div><script>const { createApp } = Vue;createApp({data() {return {seen: true,url: 'https://vuejs.org',attributeName: 'href',eventName: 'click',message: ''}},methods: {doSomething() {alert('按钮被点击了!');}}}).mount('#app');</script>

3. 条件语句

1.​​v-if / v-else​​ 基本用法:
       根据 awesome 的值显示不同的标题,添加了切换按钮和状态显示
2.​​带 key 的模板切换​​:
       使用 key 属性确保输入框在切换时重新渲染,演示了两种不同的登录表单切换
3.​​v-show​​ 用法:
       通过 display 样式控制元素显示/隐藏,对比 v-ifv-show 的区别

    <div id="app"><h2>Vue 3 条件渲染演示</h2><div><h3>1. v-if / v-else 基本用法</h3><h1 v-if="awesome">Vue is awesome!</h1><h1 v-else>Oh no 😢</h1><button @click="awesome = !awesome">切换状态</button><p>当前awesome值: {{ awesome }}</p></div><div><h3>2. 带key的模板切换</h3><template v-if="loginType === 'username'"><label>Username</label><input placeholder="Enter your username" key="username-input"></template><template v-else><label>Email</label><input placeholder="Enter your email address" key="email-input"></template><br><button @click="toggleLoginType">切换登录类型</button><p>当前登录类型: {{ loginType }}</p></div><div><h3>3. v-show 用法</h3><div v-show="isShow">这个元素会被显示/隐藏</div><button @click="isShow = !isShow">切换显示状态</button><p>当前isShow值: {{ isShow }}</p><p>注意:v-show只是切换display样式,元素始终存在于DOM中</p></div></div><script>const { createApp } = Vue;createApp({data() {return {awesome: true,loginType: 'username',isShow: true}},methods: {toggleLoginType() {this.loginType = this.loginType === 'username' ? 'email' : 'username';}}}).mount('#app');</script>

4. 循环语句

在元素上使用 v-for 指令,根据源数据的数组或对象进行循环渲染元素。

遍历数组:

v-for="(item, index) in items"

遍历对象:

v-for="(value, key, index) in object"

       key 的作用: 使用 v-for 渲染列表时,必须为每个项提供一个唯一的 key 属性,以便 Vue 能够识别每个项的唯一性,从而进行高效的 DOM 更新。

4.1 单次循环

 <div id="app"><h2>商品列表</h2><ul><li v-for="(product, index) in products" :key="product.id">{{ index + 1 }}. {{ product.name }} - ¥{{ product.price }}</li></ul><h2>用户信息</h2><div v-for="(value, key) in user" :key="key">{{ key }}: {{ value }}</div></div><script>const { createApp } = VuecreateApp({data() {return {products: [{ id: 1, name: '笔记本电脑', price: 5999 },{ id: 2, name: '智能手机', price: 3999 },{ id: 3, name: '无线耳机', price: 299 }],user: {name: '张三',age: 28,email: 'zhangsan@example.com'}}}}).mount('#app')</script>

4.2 嵌套循环

       嵌套循环: 可以嵌套使用多个 v-for 来渲染多维数组或对象结构。

 <div id="app"><h2>部门员工列表</h2><div v-for="department in departments" :key="department.name"><h3>{{ department.name }}</h3><ul><li v-for="employee in department.employees" :key="employee.id">{{ employee.name }} - {{ employee.position }}</li></ul></div></div><script>const { createApp } = VuecreateApp({data() {return {departments: [{name: '技术部',employees: [{ id: 1, name: '李四', position: '前端工程师' },{ id: 2, name: '王五', position: '后端工程师' }]},{name: '市场部',employees: [{ id: 3, name: '赵六', position: '市场经理' },{ id: 4, name: '钱七', position: '市场专员' }]}]}}}).mount('#app')</script>

5. 属性绑定

Mustache 语法不能作用在 HTML attribute 上,应该使用 v-bind指令:
v-bind 在处理 class 和 style 时, 表达式除了可以使用字符串之外,还可以是对象或数组。
v-bind:class 可以简写为 :class

<div id="app"><!-- 完整语法 --><div v-bind:id="dynamicId">动态ID元素 (完整语法)</div><!-- 简写 --><div :id="dynamicId">动态ID元素 (简写语法)</div><!-- 绑定布尔值 --><button :disabled="isButtonDisabled">可点击按钮 (当前状态: {{ isButtonDisabled ? '禁用' : '可用' }})</button><button @click="toggleButton">切换按钮状态</button><!-- 动态绑定多个值 --><div v-bind="objectOfAttrs">绑定多个属性的元素</div><!-- 显示当前状态 --><p>当前按钮禁用状态: {{ isButtonDisabled }}</p><p>objectOfAttrs 内容: {{ objectOfAttrs }}</p></div><script>const { createApp } = Vue;createApp({data() {return {dynamicId: 'my-id',isButtonDisabled: false,objectOfAttrs: {id: 'container',class: 'wrapper'}}},methods: {toggleButton() {this.isButtonDisabled = !this.isButtonDisabled;}}}).mount('#app');</script>

6. 计算属性和侦听器

1.​​计算属性​​:
       reversedMessage自动反转 message 的内容,添加按钮演示响应式更新
2.​​侦听器​​:
       监听 question 的变化,当检测到问号时自动触发回答
3.​​异步方法​​:
       模拟异步获取答案的过程,显示"思考中…"状态和最终回答

  <div id="app"><h2>Vue 3 计算属性和侦听器演示</h2><div><h3>1. 计算属性</h3><p>原始消息: "{{ message }}"</p><p>计算后反转消息: "{{ reversedMessage }}"</p><button @click="message = message + '!'">添加感叹号</button></div><div><h3>2. 侦听器和异步方法</h3><input v-model="question" placeholder="输入问题(包含问号时自动回答)"><p>回答: {{ answer }}</p><p>(提示:输入包含问号的问题,如"你好吗?")</p></div></div><script>const { createApp } = Vue;createApp({data() {return {message: 'Hello',question: '',answer: '请先输入问题'}},computed: {// 计算属性reversedMessage() {return this.message.split('').reverse().join('')}},watch: {// 侦听器question(newQuestion) {if (newQuestion.includes('?')) {this.getAnswer()}}},methods: {getAnswer() {this.answer = '思考中...'setTimeout(() => {this.answer = '这是对"' + this.question + '"的回答'}, 1000)}}}).mount('#app');</script>

7. 列表渲染

1.​​数组渲染​​
       使用v-for遍历数组,显示索引和内容
       使用:key提高性能,添加了添加/移除项目的按钮
2.​​对象渲染​​
       使用v-for遍历对象,显示键、值和索引
3.​​范围渲染​​
       使用v-for渲染1-10的数字
4.​​template渲染​​:
       使用<template>标签渲染多个元素,为每个项目添加分隔线

 <div id="app"><h2>Vue 3 列表渲染演示</h2><div><h3>1. 数组渲染 (带索引和key)</h3><ul><li v-for="(item, index) in items" :key="item.id">{{ index }} - {{ item.message }} (ID: {{ item.id }})</li></ul><button @click="addItem">添加项目</button><button @click="removeItem">移除项目</button></div><div><h3>2. 对象渲染 (键值对)</h3><ul><li v-for="(value, key, index) in myObject">{{ index }}. {{ key }}: {{ value }}</li></ul></div><div><h3>3. 范围渲染 (1-10)</h3><div><span v-for="n in 10">{{ n }} </span></div></div><div><h3>4. 使用template渲染多个元素</h3><ul><template v-for="item in items"><li>{{ item.message }}</li><li class="divider" role="presentation"></li></template></ul></div><div><h3>当前数据状态</h3><pre>{{ JSON.stringify({ items, myObject }, null, 2) }}</pre></div></div><script>const { createApp } = Vue;createApp({data() {return {items: [{ id: 1, message: 'Foo' },{ id: 2, message: 'Bar' }],myObject: {title: 'How to do lists in Vue',author: 'Jane Doe',publishedAt: '2025-01-01'},nextId: 3}},methods: {addItem() {this.items.push({id: this.nextId++,message: 'New Item ' + (this.nextId - 1)});},removeItem() {if (this.items.length > 0) {this.items.pop();}}}}).mount('#app');</script>

8. 表单输入绑定

1.​​文本输入​​ - 基本的v-model绑定
2.​​多行文本​​ - textarea的使用
3.​​单个复选框​​ - 绑定布尔值
4.​​多个复选框​​ - 绑定数组
5.​​单选按钮​​ - 绑定单个值
6.​​选择框​​ - select和option的使用
7.​​修饰符​​:
       .lazy - 在change时而非input时更新
       .number - 自动转为数字类型
       .trim - 自动去除首尾空格

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vue 3 表单绑定示例</title><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script><style>div {margin: 15px 0;padding: 10px;border: 1px solid #eee;border-radius: 5px;}input, textarea, select {margin: 5px;padding: 5px;}</style>
</head>
<body><div id="app"><h2>Vue 3 表单绑定演示</h2><!-- 文本输入 --><div><h3>1. 文本输入</h3><input v-model="text" placeholder="编辑我"><p>文本是: {{ text || '空' }}</p></div><!-- 多行文本 --><div><h3>2. 多行文本</h3><textarea v-model="message" placeholder="添加多行文本"></textarea><p>多行文本是: <pre>{{ message || '空' }}</pre></p></div><!-- 单个复选框 --><div><h3>3. 单个复选框</h3><input type="checkbox" id="checkbox" v-model="checked"><label for="checkbox">状态: {{ checked }}</label></div><!-- 多个复选框 --><div><h3>4. 多个复选框</h3><input type="checkbox" id="jack" value="Jack" v-model="checkedNames"><label for="jack">Jack</label><input type="checkbox" id="john" value="John" v-model="checkedNames"><label for="john">John</label><input type="checkbox" id="mike" value="Mike" v-model="checkedNames"><label for="mike">Mike</label><p>选中的名字: {{ checkedNames.length ? checkedNames : '无' }}</p></div><!-- 单选按钮 --><div><h3>5. 单选按钮</h3><input type="radio" id="one" value="One" v-model="picked"><label for="one">One</label><input type="radio" id="two" value="Two" v-model="picked"><label for="two">Two</label><p>选中的是: {{ picked || '无' }}</p></div><!-- 选择框 --><div><h3>6. 选择框</h3><select v-model="selected"><option disabled value="">请选择</option><option>A</option><option>B</option><option>C</option></select><p>选中的是: {{ selected || '无' }}</p></div><!-- 修饰符 --><div><h3>7. 修饰符</h3><div><label>.lazy修饰符 (change时更新):</label><input v-model.lazy="msg"><p>值: {{ msg || '空' }}</p></div><div><label>.number修饰符 (转为数字):</label><input v-model.number="age" type="number"><p>类型: {{ typeof age }}, 值: {{ age }}</p></div><div><label>.trim修饰符 (去除首尾空格):</label><input v-model.trim="trimmedMsg"><p>值: "{{ trimmedMsg || '空' }}"</p></div></div><div><h3>当前所有数据状态</h3><pre>{{ JSON.stringify({text,message,checked,checkedNames,picked,selected,msg,age,trimmedMsg}, null, 2) }}</pre></div></div><script>const { createApp } = Vue;createApp({data() {return {text: '',message: '',checked: false,checkedNames: [],picked: '',selected: '',msg: '',age: 0,trimmedMsg: ''}}}).mount('#app');</script>
</body>
</html>

9. 事件处理

9.1 事件绑定语法​​

       完整写法:v-on:click="methodName"
       简写形式:@click="methodName"

  <div id="app"><h2>Vue3 事件处理</h2><p>计数器: {{ count }}</p><!-- 使用v-on:click --><button v-on:click="increment">增加 (v-on语法)</button><!-- 使用@click简写 --><button @click="decrement">减少 (@简写)</button><!-- 带参数的事件 --><button @click="sayHello('Vue3')">打招呼</button><!-- 访问原生DOM事件 --><button @click="showEventInfo($event)">显示事件信息</button><!-- 事件修饰符示例 --><div @click="parentClick" style="padding:20px; background:#eee; margin-top:20px;"><button @click.stop="childClick">阻止冒泡(.stop)</button></div></div><script>const { createApp } = VuecreateApp({data() {return {count: 0}},methods: {increment() {this.count++console.log('计数器增加')},decrement() {this.count--console.log('计数器减少')},sayHello(name) {alert(`你好,${name}!`)},showEventInfo(event) {console.log('事件对象:', event)console.log('触发元素:', event.target)},parentClick() {console.log('父元素点击')},childClick() {console.log('子元素点击(不会冒泡)')}}}).mount('#app')</script>

当点击按钮时,事件会:
       1.先触发按钮的childClick
       2.然后向上冒泡触发父元素的parentClick

9.2 为什么要阻止冒泡?

有时我们不希望事件向上传播,例如:
       1.点击下拉菜单项时,不希望触发关闭菜单的事件
       2.点击模态框内容时,不希望触发关闭模态框的事件
       3.嵌套的可点击元素需要独立处理各自的事件

 <div id="app"><h2>阻止事件冒泡示例</h2><div @click="logEvent('父元素被点击')"><button @click="logEvent('按钮被点击(会冒泡)')">普通按钮</button><button @click.stop="logEvent('按钮被点击(阻止冒泡)')">阻止冒泡按钮(.stop)</button></div><div><p v-for="(log, index) in logs" :key="index">{{ log }}</p></div></div><script>const { createApp } = VuecreateApp({data() {return {logs: []}},methods: {logEvent(message) {this.logs.push(`${new Date().toLocaleTimeString()}: ${message}`);console.log(message);}}}).mount('#app')</script>

六、组件

1. 组件基础

       组件是 Vue 的核心功能之一,它允许我们将 UI 划分为独立可复用的部分。

       1. 组件是可复用的 Vue 实例
       2. 使用 components选项注册组件
       3. 组件名在模板中使用时通常使用 kebab-case(短横线分隔命名)
       4. 每个组件必须有单个根元素

 <div id="app"><greeting></greeting><greeting></greeting></div><script>const { createApp } = Vue;// 定义一个组件const Greeting = {template: `<p>你好,我是Vue组件!</p>`};const app = createApp({// 注册组件components: {Greeting}});app.mount('#app');</script>

kebab-case 是一种常见的编程命名约定,在计算机科学与软件开发的诸多领域中被广泛应用。 它得名于英文中的 kebab,即烤肉串。 之所以命名为 kebab-case,是因为这种命名方式的形式像一串连在一起的词语,通过短横线(或称为连字符)相连接,形似烤肉串中的各个肉块被串在一起。 例如,字符串hello-world就是 kebab-case 的一个典型例子。

2. 组件 Props

       Props父组件向子组件传递数据的方式

       1. Props 是组件的自定义属性

       2. 子组件通过 props选项声明它接受的属性

       3. 父组件通过属性方式传递数据

       4. 推荐使用 kebab-case 命名属性(HTML 特性不区分大小写)

 <div id="app"><user-card name="张三" age="25"job="前端开发"></user-card><user-card name="李四" age="30"job="UI设计师"></user-card></div><script>const { createApp } = Vue;const UserCard = {props: ['name', 'age', 'job'],template: `<div><h3>{{ name }}</h3><p>年龄: {{ age }}</p><p>职业: {{ job }}</p></div>`};const app = createApp({components: {UserCard}});app.mount('#app');</script>

​​父组件​​是 app(根组件),它被挂载到 #app元素上。父组件中注册了 UserCard组件。
​​子组件​​是 UserCard,它通过 props接收父组件传递的数据(name、age、job)。

具体关系:
       • 父组件(根组件)在模板中使用了<user-card>标签
       • 子组件 UserCard通过 props 接收父组件传递的数据
       • 父组件向子组件传递数据的方式是通过 <user-card>标签的属性(name=“张三” 等)

总结:

  • 父:挂载到 #app的根组件
  • 子:UserCard组件

3. 组件事件

       子组件可以通过事件与父组件通信

       1. 子组件通过 $emit触发事件

       2. 父组件通过 v-on@ 监听子组件事件

       3. 事件名推荐使用 kebab-case

       4. 可以传递参数:$emit('event-name', arg1, arg2)

  <div id="app"><p>计数器: {{ count }}</p><counter-button @increment="count++"></counter-button></div><script>const { createApp } = Vue;const CounterButton = {template: `<button @click="$emit('increment')">增加计数</button>`};const app = createApp({data() {return {count: 0}},components: {CounterButton}});app.mount('#app');</script>

4. 插槽

       插槽允许组件接收模板片段作为内容。

       1. <slot> 元素作为内容分发的出口

       2. 父组件模板中放入组件标签之间的内容会替换子组件的 <slot>

       3. 可以有默认内容:<slot>默认内容</slot>

       4. 具名插槽允许有多个插槽

  <div id="app"><alert-box>这是一个重要的消息!</alert-box><alert-box><strong>警告!</strong> 系统即将关闭。</alert-box></div><script>const { createApp } = Vue;const AlertBox = {template: `<div style="border: 1px solid #ccc; padding: 10px; margin: 5px;"><slot></slot></div>`};const app = createApp({components: {AlertBox}});app.mount('#app');</script>

接下来让我们仔细看看插槽到底是怎么渲染的

4.1 Vue 组件定义部分

const AlertBox = {template: `<div style="border: 1px solid #ccc; padding: 10px; margin: 5px;"><slot></slot></div>`
};

       • 定义了一个名为 AlertBox的组件

       • 组件模板包含一个带有边框样式的 div

       • <slot> </slot>是插槽的位置,这里的内容会被父组件中 <alert-box>标签内的内容替换

4.2 插槽(Slot)的工作原理

  1. 父组件(这里就是 #app)在 标签内放置内容

  2. 子组件(AlertBox)通过 标签定义内容插入的位置

  3. Vue 会自动将父组件中的内容插入到子组件的 位置

4.3 最终渲染结果

第一个 <alert-box>会渲染为:

<div style="border: 1px solid #ccc; padding: 10px; margin: 5px;">这是一个重要的消息!
</div>

第二个 <alert-box>会渲染为:

<div style="border: 1px solid #ccc; padding: 10px; margin: 5px;"><strong>警告!</strong> 系统即将关闭。
</div>

插槽让组件更加灵活,可以:

  • 在组件内部预留位置由使用者决定插入什么内容
  • 创建可复用的布局组件
  • 允许组件接收复杂的HTML结构而不仅仅是简单的数据

5. 动态组件

       动态组件可以在多个组件间动态切换。

       1. 使用 <component :is="..."> 实现动态组件

       2. is 的值可以是已注册组件的名字或组件选项对象

       3. 动态切换组件时,默认会销毁和重新创建组件实例

       4. 可以使用 <keep-alive> 缓存不活动的组件实例

<!DOCTYPE html>
<html>
<head><title>Vue3 动态组件</title><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body><div id="app"><button @click="currentComponent = 'home'">首页</button><button @click="currentComponent = 'about'">关于</button><button @click="currentComponent = 'contact'">联系</button><component :is="currentComponent"></component></div><script>const { createApp } = Vue;const Home = {template: `<div>这是首页内容</div>`};const About = {template: `<div>这是关于我们的内容</div>`};const Contact = {template: `<div>这是联系方式</div>`};const app = createApp({data() {return {currentComponent: 'home'}},components: {Home,About,Contact}});app.mount('#app');</script>
</body>
</html>

5.1 组件定义部分

const Home = {template: `<div>这是首页内容</div>`
};const About = {template: `<div>这是关于我们的内容</div>`
};const Contact = {template: `<div>这是联系方式</div>`
};

       定义了三个简单的组件:HomeAboutContact

5.2 Vue 应用配置

const app = createApp({data() {return {currentComponent: 'home' // 默认显示Home组件}},components: {Home,About,Contact}
});

       • 在 data 中定义了 currentComponent变量,初始值为 ‘home’

       • 注册了三个组件

5.3 模板部分

<button @click="currentComponent = 'home'">首页</button>
<button @click="currentComponent = 'about'">关于</button>
<button @click="currentComponent = 'contact'">联系</button><component :is="currentComponent"></component>

       • 三个按钮分别点击时修改 currentComponent 的值

       • <component :is="currentComponent"> 会根据 currentComponent 的值动态渲染对应的组件

从用户体验角度:推荐组件放在按钮后​
<component :is="currentComponent"></component> 放在前三个按钮的后面

七、Vue3常用指令速查表

1.常用指令

指令缩写说明示例
v-text-更新元素的文本内容<span v-text="message"></span>
v-html-更新元素的innerHTML<div v-html="rawHtml"></div>
v-show-根据条件显示/隐藏元素(display切换)<div v-show="isVisible">内容</div>
v-if-条件渲染元素(销毁/重建)<div v-if="isActive">内容</div>
v-else-必须跟在v-if/v-else-if后<div v-else>其他内容</div>
v-else-if-v-if的"else if"块<div v-else-if="type === 'B'">B</div>
v-for-循环渲染元素<li v-for="item in items" :key="item.id">{{ item.text }}</li>
v-on@绑定事件监听器<button @click="doThis">点击</button>
v-bind:动态绑定属性<img :src="imageSrc">
v-model-表单输入双向绑定<input v-model="message">
v-slot#定义插槽内容<template #header><h1>标题</h1></template>
v-pre-跳过编译<div v-pre>{{ 这里不编译 }}</div>
v-once-只渲染一次<span v-once>{{ 不会改变 }}</span>
v-memo-缓存模板子树<div v-memo="[valueA, valueB]">...</div>
v-cloak-隐藏未编译的模板[v-cloak] { display: none }

2.修饰符速查

2.1 v-model 修饰符

修饰符说明示例
.lazy改为change事件触发<input v-model.lazy="msg">
.number输入转为数字<input v-model.number="age">
.trim去除首尾空格<input v-model.trim="text">

2.2 v-on 修饰符

修饰符说明示例
.stop阻止事件冒泡<button @click.stop="doThis">
.prevent阻止默认行为<form @submit.prevent="onSubmit">
.capture使用捕获模式<div @click.capture="doThis">
.self仅当event.target是元素自身触发<div @click.self="doThat">
.once只触发一次<button @click.once="doThis">
.passive提升滚动性能<div @scroll.passive="onScroll">

2.3 按键修饰符

修饰符说明示例
.enter回车键<input @keyup.enter="submit">
.tabTab键<input @keyup.tab="nextField">
.delete删除/退格键<input @keyup.delete="clear">
.escESC键<input @keyup.esc="cancel">
.space空格键<button @keyup.space="jump">
.up上箭头<input @keyup.up="moveUp">
.down下箭头<input @keyup.down="moveDown">
.left左箭头<input @keyup.left="moveLeft">
.right右箭头<input @keyup.right="moveRight">

八、自定义指令

1. 什么是自定义指令?

       自定义指令是 Vue 提供的强大功能,允许你直接操作 DOM 元素。当内置指令不够用时,自定义指令可以扩展 Vue 的能力。

2. 基本语法

2.1 全局注册

       全局注册可以在任何 Vue 实例的模板中使用

const app = createApp({})// 注册一个全局自定义指令 `v-focus`
app.directive('focus', {mounted(el) {el.focus()}
})

2.2 局部注册

       局部注册只能在该组件及其子组件中使用

const MyComponent = {directives: {focus: {mounted(el) {el.focus()}}},template: `<input v-focus>`
}

3. 钩子函数速查表

钩子函数调用时机参数使用场景示例
created绑定元素的 attribute 或事件监听器应用之前el, binding, vnode在绑定前修改元素属性
beforeMount元素被插入到 DOM 前调用el, binding, vnode准备 DOM 操作前的初始化
mounted元素被插入到 DOM 后调用el, binding, vnode最常见的 DOM 操作时机(如添加事件监听)
beforeUpdate在包含组件的 VNode 更新前调用el, binding, vnode, prevVnode更新前清理旧状态
updated在包含组件的 VNode 及其子组件的 VNode 更新后调用el, binding, vnode, prevVnode更新后执行 DOM 操作
beforeUnmount在绑定元素的父组件卸载前调用el, binding, vnode清理即将卸载的组件(如定时器)
unmounted在绑定元素的父组件卸载后调用el, binding, vnode最终清理工作

参数说明

  • el:指令绑定的 DOM 元素
  • binding:包含以下属性的对象:
    • value:指令的绑定值
    • oldValue:之前的值(仅在 updatecomponentUpdated 中可用)
    • arg:指令参数(如 v-my-directive:foo 中的 foo
    • modifiers:包含修饰符的对象(如 v-my-directive.foo.bar 中的 { foo: true, bar: true }
    • instance:使用指令的组件实例
  • vnode:Vue 编译生成的虚拟节点
  • prevVnode:上一个虚拟节点(仅在 updatecomponentUpdated 钩子中可用)

生命周期流程图

created → beforeMount → mounted → beforeUpdate → updated → beforeUnmount → unmounted

提示:大多数情况下只需使用 mountedupdated 钩子即可满足需求

http://www.xdnf.cn/news/1319041.html

相关文章:

  • 说一下事件传播机制
  • Python注解
  • Python入门第7课:异常处理机制:让你的程序更健壮(try-except详解)
  • 配置 NVIDIA RTX 5090 + sm_120 + flashattention,已跑通一个大模型 ~~
  • C语言(12)——进阶函数
  • Day3--滑动窗口与双指针--2461. 长度为 K 子数组中的最大和,1423. 可获得的最大点数,1052. 爱生气的书店老板
  • 数字货币的法律属性与监管完善路径探析
  • 实变函数中集合E的边界与其补集的边界是否相等
  • Android中使用Compose实现各种样式Dialog
  • Dify 从入门到精通(第 40/100 篇):Dify 的企业级权限管理
  • Mutually aided uncertainty
  • Windchill 11.0使用枚举类型自定义实用程序实现生命周期状态管理
  • Makefile介绍(Makefile教程)(C/C++编译构建、自动化构建工具)
  • 计算机网络 TCP、UDP 区别
  • 从需求到部署全套方案:餐饮服务许可证数据可视化分析系统的大数据技术实战
  • Bee1.17.25更新Bug,完善功能.不支持NOSQL,分库分表Sharding(2.X版有)
  • C语言网络编程TCP通信实战:客户端↔服务器双向键盘互动全流程解析
  • 模拟实现 useEffect 功能
  • 【R语言】R 语言中打印含有双引号的字符串时会出现 “\” 的原因解析
  • 基于STM32单片机智能RFID刷卡汽车位锁桩设计
  • 基于51单片机汽车自动照明灯超声波光敏远近光灯设计
  • 自由学习记录(85)
  • TensorRT-LLM.V1.1.0rc0:在无 GitHub 访问权限的服务器上编译 TensorRT-LLM 的完整实践
  • 计算机网络 TCP time_wait 状态 详解
  • Java开发MCP服务器
  • thingsboard 服务器在2核CPU、2G内存资源配置下如何调优提速,适合开发/演示
  • vue封装请求拦截器 响应拦截器
  • 计算机网络 Session 劫持 原理和防御措施
  • 给纯小白的Python操作 PDF 笔记
  • 【算法】模拟专题