JavaWeb_第7章_Vue.js
第7章 Vue.js
7.1 Vue概述
7.1.1 Vue简介
Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。官网为:https://cn.vuejs.org/
Vue作者:尤雨溪
Vue的两个核心功能:
- 声明式渲染:Vue 基于标准 HTML 拓展了一套模板语法,使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。
- 响应性:Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 DOM
7.1.2 Vue开发环境
1、Node.js
Node.js(https://node.org.cn)是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,可以使 JavaScript 运行在服务器端。使用 Node.js,可以方便地开发服务器端应用程序,如 Web 应用、API、后端服务,还可以通过 Node.js 构建命令行工具等。相比于传统的服务器端语言(如 PHP、Java、Python 等),Node.js 具有以下特点:
- 单线程,但是采用了事件驱动、异步 I/O 模型,可以处理高并发请求。
- 轻量级,使用 C++ 编写的 V8 引擎让 Node.js 的运行速度很快。
- 模块化,Node.js 内置了大量模块,同时也可以通过第三方模块扩展功能。
- 跨平台,可以在 Windows、Linux、Mac 等多种平台下运行。
-
安装方式见教材p195
-
检查是否安装完成
node -v
2、npm 包管理工具
NPM全称Node Package Manager,是Node.js包管理工具,是全球最大的模块生态系统,里面所有的模块都是开源免费的;也是Node.js的包管理工具,相当于后端的Maven 。
安装node,自动安装npm包管理工具!
-
配置阿里镜像
npm config set registry https://registry.npmmirror.com -
确认配置已生效
npm config get registry -
npm常用命令
npm -v # 查看npm的版本 npm install 包名 #可以简写为“npm i 包名”,用于为项目安装指定名称的包。如果加上-g选项,则会把包安装为全局包,否则只安装到本项目中。 npm uninstall 包名 #用于卸载指定名称的包。 npm update 包名 #用于更新指定名称的包。
3、Vue CLI
Vue CLI是一个Vue的官方命令行工具,它提供了构建、开发和部署Vue应用的脚手架,用于快速、便捷地创建和管理Vue项目。Vue CLI参考
-
安装Vue CLI,具体命令如下:
npm install -g @vue/cli # 全局安装vue脚手架 -
查看安装是否成功
vue -V
7.2 Vue项目的创建和执行过程
7.2.1 Vue项目的创建
(1)打开用于存放项目的文件夹,在地址栏中输入cmd后按“Enter”键,在当前目录下打开命令提示符窗口,并通过如下命令创建一个名称为“chapter07”的项目。
vue create chapter07
(2)执行完上述命令后,需要选择项目创建的预设配置:选择Vue3,按”Enter“键

(3)命令行窗口会继续提示选择什么包管理工具:选择”Use NPM“,按”Enter“键

(4)完成创建

(5)通过“cd chapter07”命令进入到项目的目录,然后执行“npm run serve”命令启动chapter07项目的服务。

(6)chapter07项目启动成功后,可以通过本地服务器中的8080端口进行访问。在浏览器中访问http://localhost:8080/进入项目的欢迎页面。(Ctrl+C停止项目运行)

(7)使用IDEA工具打开chapter07项目,可以看到一个默认生成的项目目录结构。

chapter07/ # 项目根目录
├── node_modules/ # 项目的依赖库目录,通过npm install安装的所有依赖包都存放在这里
├── public/ # 静态资源目录,需要使用绝对路径访问
│ ├── index.html # 默认的主渲染页面文件,同时也是页面的入口文件
├── src/ # 源代码目录,我们编写代码的地方
│ ├── assets/ # 资源目录,存放图片、字体、样式等资源,需要使用相对路径访问
│ ├── components/ # 组件目录,存放可复用的Vue组件
│ │ ├── HelloWorld.vue # 示例组件,一个Vue单文件组件
│ ├── App.vue # 应用的根组件,所有其他组件都将作为其子组件
│ └── main.js # 应用入口文件,在这里创建Vue应用实例并挂载到DOM
├── package.json # 项目配置文件,定义了项目的基本信息、依赖和脚本命令
└── vue.config.js # Vue CLI的配置文件,用于自定义构建配置和开发服务器配置
(8)打开IDEA终端工具运行Vue项目或配置IDEA工具快捷运行Vue项目(可选)

7.2.2 Vue项目的执行过程
当执行“npm run serve”命令启动一个Vue项目时,项目会通过main.js文件将App.vue组件渲染到index.html文件指定的区域,从而在页面上显示内容。
-
App.vue:Vue项目是由各种组件组成的,App.vue是项目的根组件。在根组件中可以引入其他组件,从而显示其他组件的内容
<template> <img alt="Vue logo" src="./assets/logo.png"> <!-- 使用子组件 --> <HelloWorld msg="Welcome to Your Vue.js App"/> </template> <script> // 导入子组件 import HelloWorld from './components/HelloWorld.vue' // 导出组件,Vue组件书写风格之一:选项式API(Options API) export default { name: 'App', components: { HelloWorld } } </script> <!--样式--> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style> -
main.js:main.js文件是项目的入口文件,该文件创建了Vue应用实例,Vue应用实例是Vue项目工作的基础
// 导入createApp()函数,用于创建Vue应用实例 import { createApp } from 'vue' // 导入App.vue,并保存为App变量 import App from './App.vue' // 创建Vue应用实例,并挂载到index.html文件中的#app元素上 createApp(App).mount('#app') -
index.html:index.html文件是页面的入口文件,它负责加载和初始化项目所需的资源和组件,为用户提供一个与网站交互的页面。
<!DOCTYPE html> <html lang=""> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>- 虽然在 index.html 中看不到 main.js 的引入,但在构建过程中,main.js 的内容会被打包并自动添加到 HTML 页面中
7.3 Vue开发基础
7.3.1 单文件组件
什么是VUE的组件?
- 一个页面作为整体,是由多个部分组成的,每个部分在这里就可以理解为一个组件
- 每个.vue文件就可以理解为一个组件,多个.vue文件可以构成一个整体页面
- 组件化给我们带来的另一个好处就是组件的复用和维护非常的方便

什么是.vue文件?
-
传统的页面有.html文件.css文件和.js文件三个文件组成(多文件组件)
-
vue将这文件合并成一个.vue文件(Single-File Component,简称 SFC,单文件组件)
-
.vue文件对js/css/html统一封装,这是VUE中的概念 该文件由三个部分组成
<script> <template> <style>- template标签 代表组件的html部分代码 代替传统的.html文件
- script标签 代表组件的js代码 代替传统的.js文件
- style标签 代表组件的css样式代码 代替传统的.css文件
<template> <!-- 组件的模板代码 --> </template> <script setup> // 组件的逻辑代码 </script> <style scoped> /* 组件的样式代码 */ </style>
7.3.2 数据绑定
1、定义数据
在一个Web应用中,页面中的数据通常是动态变化的,为了更方便地处理这些数据,Vue提供了数据绑定功能,能够将数据轻松地绑定到DOM中。绑定数据首先需要在
<template>
{{ 数据名 }}
</template>
<script>
export default {
setup(){
return{
数据名:数据值,
// ……
}
}
}
</script>
setup()函数是Vue3中特有的,在该函数中可以定义数据和方法,并且要通过一个return关键字返回一个对象,用于将对象中的数据暴露给模板和组件实例;
<script>
export default {
setup() {
let count = 1
let person = {
name: '张三',
age: 18
}
let flag = true
return {
count,
person,
flag
}
}
}
</script>
为了让代码更简洁,Vue3中还提供了setup语法糖(Syntactic Sugar),它可以简化在<script>标签中定义数据的语法格式,具体格式如下(:
<!--setup语法糖-->
<script setup>
const count = 1
const person = {
name: '张三',
age: 18
}
const flag = true
</script>
2、获取数据
Vue提供的Mustache语法(又称为双大括号语法)用于在模板中放入占位符。当页面渲染时,{{ 数据名 }}会被替换为对应的数据值。
在Mustache语法中,还可以将表达式的值作为输出内容,表达式的值可以是字符串、数字等类型,示例代码如下。
<template>
<div>
<button @click="count++">Count is {{ count }}</button><br>
{{ 'Hello Vue.js' }}<br>
{{ count + 1 }}<br>
{{ person.name }}<br>
{{ flag ? 'a' : 'b' }}
</div>
</template>
<script>
// 同上
</script>
7.3.3 ref()函数和reactive()函数
在Vue3中,数据默认是非响应式的,也就是说,将数据定义出来并在页面中显示后,如果后续修改了数据,页面中显示的数据不会同步更新。为此,Vue 3提供了两个函数ref()和reactive(),用于绑定响应式的数据。
1、ref()函数
ref()函数用于将数据转换为响应式数据。使用ref()函数定义响应式数据的语法格式如下。
<script setup>
import {ref} from "vue"; // 引入ref()函数
const count = ref(1) // 定义响应式数据
</script>
ref()函数处理的响应式数据在js编码修改的时候需要通过.value操作,而ref响应式数据在绑定到html上时不需要.value
<template>
<div>
<button @click="count++">Count is {{ count }}</button>
</div>
</template>
<script setup>
import {ref} from "vue";// 引入ref
const count = ref(1)
setTimeout(() => {
count.value = 1000000
}, 2000)
</script>
@click是Vue指令v-on的语法糖,v-on指令后文会讲解
修改代码:增加两个按钮,一个控制count加1,一个控制count减1
ESLint问题:①配置文件;②IDEA
Vue文件中的缩进问题,setting>Editor>code style>Vue template>Indent children of top-level tag: template,script,style
2、reactive()函数
reactive()函数用于创建一个响应式的对象或数组,具体语法格式如下。
<script setup>
import {reactive} from "vue"; // 引入reactive
// 定义响应式对象
const person = reactive({
name: '张三',
age: 18
})
</script>
函数中要操作reactive处理过的数据,需要通过 对象名.属性名的方式,在模板中使用时,也使用 对象名.属性名
<template>
<div>
姓名:{{ person.name }}<br>
年龄:{{ person.age }}
</div>
</template>
<script setup>
import {reactive} from "vue"; // 引入reactive
// 定义响应式对象
const person = reactive({
name: '张三',
age: 18
})
// 2秒后修改数据
setTimeout(() => {
person.name = '王五'
person.age = 20
}, 2000)
</script>
3、ref()与reactive()
-
ref()可以定义响应式数据,包括对象,通常用于定义基本类型(如字符串、数字、布尔值)的响应式数据,而当用于对象时,实际上内部会调用reactive函数来使对象具有响应性。
-
使用ref()函数来定义响应式对象时,修改对象也需要使用.value
<script> import { ref } from 'vue' // 定义对象响应式 const user = ref({ name: '张三', age: 25, address: { city: '北京' } }) // 访问和修改 console.log(user.value.name) // 获取 user.value.name = '李四' // 修改 user.value.age = 26 // 修改 </script> -
reactive()函数 可以将一个普通对象转化为响应式对象,这样在数据变化时会自动更新界面,特别适用于处理复杂对象或者数据结构。
-
综上所述,
ref适用与简单情形下的数据双向绑定,对于只有一个字符等基本类型数据或自定义组件等情况,建议可以使用ref;而对于对象、函数等较为复杂的数据结构,以及需要递归监听的属性变化,建议使用reactive。当然,在实际项目中根据需求灵活选择也是十分必要的。
7.4 Vue指令
在实际开发中,经常需要操作页面中的元素并与之进行交互,例如动态修改元素的文本内容、为元素绑定事件、控制元素的显示与隐藏等。为此,Vue提供了一系列指令,它们是以v-为前缀的特殊属性。通过这些指令,开发者能够使用更简洁的代码实现这些功能。
7.4.1 v-bind和v-model
1、v-bind
v-bind用于为元素属性动态地绑定属性值,v-bind的语法格式如下。
<标签名 v-bind:属性名="数据"></标签名>
上述语法格式还可以简写为如下形式。
<标签名 :属性名="数据"></标签名>
具体使用
<template>
<div>
<a
v-bind:href='data.url'
target="_self">
<img
style="width: 100px;background:#8c271e;"
:src="data.logo"
:title="data.name">
<br>
<input type="button"
:value="`点击访问${data.name}`">
</a>
</div>
</template>
<script setup>
const data = {
name:'科成',
url:"https://www.cduestc.cn/",
logo:"https://www.cduestc.cn/image/main/logo.png"
}
</script>
2、v-model
在处理表单信息时,经常需要将表单输入框中的内容同步给JavaScript中相应的变量,如果使用原生JavaScript代码实现,还需要手动选择输入框元素并添加事件监听器,代码会比较烦琐,而通过v-model可以非常方便地实现这一功能。
单项绑定和双向绑定
- 单向绑定: 响应式数据的变化会更新dom树,但是dom树上用户的操作造成的数据改变不会同步更新到响应式数据
- 双向绑定: 响应式数据的变化会更新dom树,但是dom树上用户的操作造成的数据改变会同步更新到响应式数据
- 用户通过表单标签才能够输入数据,所以双向绑定都是应用到表单标签上的,其他标签不行
- v-model专门用于双向绑定表单标签的value属性,语法为
v-model:value='',可以简写为v-model='' - v-model还可以用于各种不同类型的输入,
<textarea>、<select>元素。
v-model用于实现表单元素的双向数据绑定,其语法格式如下。
<标签名 v-model="数据"></标签名>
具体使用
<template>
<div>
<input v-model="name"><br>
欢迎你,{{ name }}
</div>
</template>
<script setup>
import {ref} from "vue";
const name = ref('张三')
</script>
假设有一个表单,用于收集个人信息,代码应该如何修改?
<template>
<div>
姓名:<input v-model="person.name"><br>
年龄:<input v-model="person.age"><br>
性别:
<select v-model="person.sex">
<option value="男">男</option>
<option value="女">女</option>
</select> <br>
<button @click="submit()">提交</button>
</div>
</template>
<script setup>
import {reactive} from "vue";
const person = reactive({
name: '',
age: '',
sex: ''
})
function submit() {
// alert(`姓名:${person.name},年龄:${person.age},性别:${person.sex}`)
}
</script>
7.4.2 v-on
我们可以使用 v-on 来监听 DOM 事件,并在事件触发时执行对应的 Vue的JavaScript代码。
语法格式如下:
<标签名 v-on:事件名="handler"></标签名>
可以简写为:
<标签名 @事件名="handler"></标签名>
handler的值可以是方法事件处理器,也可以是内联事件处理器,vue中的事件名=原生事件名去掉on 前缀 如:onclick --> click,事件参考:HTML DOM 事件对象 | 菜鸟教程
比如:
<!-- 方法事件处理器 -->
<button @click="submit">提交</button>
<!-- 内联事件处理器 -->
<button @click="count++">提交</button>
绑定事件时,可以通过一些绑定的修饰符,常见的事件修饰符如下:
.once:只触发一次事件。[重点].prevent:阻止默认事件。[重点]- .stop:阻止事件冒泡。
- .capture:使用事件捕获模式而不是冒泡模式。
- .self:只在事件发送者自身触发时才触发事件。
具体使用:
<template>
<div>
<h1>count的值是{{ count }}</h1>
<!--方法事件处理器-->
<button v-on:click="addCount()">addCount(方法事件处理器)</button>
<!--内联事件处理器-->
<button v-on:click="count++">count++(内联事件处理器)</button>
<!--事件修饰符 once 只绑定事件一次-->
<button @click.once="count++">addOnce(只触发一次)</button>
<!--事件修饰符 prevent 组织组件的默认事件-->
<a href="https://www.baidu.com" @click.prevent="count++">不会跳转百度</a>
<!--原生js方式阻止组件默认行为-->
<a href="https://www.baidu.com" @click.prevent="incrCount($event)">不会跳转百度</a>">
</div>
</template>
<script setup>
import {ref} from "vue";
let count = ref(0)
let addCount = () => {
count.value++
}
let incrCount = (event) => {
count.value++
// 通过事件对象组织组件的默认行为
event.preventDefault()
}
</script>
事件绑定中的函数传参
-
自动传递事件对象
<template> <!-- 自动传递 $event 对象 --> <button @click="doThis">按钮1</button> <!-- 不传递 $event 对象 --> <button @click="doThis()">按钮2</button> <!-- 手动传递 $event 对象 --> <button @click="doThis($event)">按钮3</button> </template> <script setup> function doThis(event) { console.log(event) // 对于按钮1:MouseEvent 对象 // 对于按钮2:undefined // 对于按钮3:MouseEvent 对象 } </script> -
传递自定义参数
<template> <!-- 可以传递自定义参数 --> <button @click="doThis('hello', 123)">按钮</button> <!-- 需要手动传递 $event 对象 --> <button @click="doThis('hello', 123, $event)">按钮</button> </template> <script setup> function doThis(arg1, arg2, event) { console.log(arg1, arg2, event) // 'hello', 123, MouseEvent } </script>
7.4.3 v-if和v-show
1、v-if
v-if用于根据条件决定是否添加或删除DOM元素来实现条件渲染。当条件为真时,元素会被添加到DOM中;当条件为假时,元素会从DOM中移除。
<标签名v-if="条件"></标签名>
也可以使用v-else-if或 v-else 为 v-if 添加一个“else 区块”。注意一个 v-else-if或 v-else 元素必须跟在一个 v-if 元素后面,否则它将不会被识别
<标签名v-if="条件A">元素A</标签名>
<标签名v-else-if="条件B">元素B</标签名>
<标签名v-else>元素C</标签名>
具体使用:定义一个输入框,根据输入的分数判定成绩等级
<template>
<div>
请输入您的分数:
<input type="text" v-model="score"><br><br>
您的等级为:
<p v-if="score >= 90">优秀</p>
<p v-else-if="score >= 60">及格</p>
<p v-else>不及格</p>
</div>
</template>
<script setup>
import {ref} from 'vue';
const score = ref('50')
</script>
2、v-show
v-show也可以用于根据条件控制元素的显示与隐藏,但是它与v-if不同的是,v-show的原理是通过设置元素的样式属性display来控制它的显示与隐藏。当v-show的条件为假时,会为元素添加display:none样式,反之则不添加。
v-show的条件无论如何变化,元素都不会从DOM中移除,因此v-show更适合于频繁切换显示与隐藏的场景,因为它不需要频繁操作DOM,性能相对较高。
v-show的语法格式与v-if单独使用时相同。
<template>
<div>
<p v-if="flag">v-if控制的元素</p>
<p v-show="flag">v-show控制的元素</p>
<button @click="flag = !flag">显示/隐藏</button>
</div>
</template>
<script setup>
import {ref} from 'vue';
const flag = ref(true)
</script>
注:
-
打开浏览器控制台,查看元素,观察页面标签变化

-
v-show不支持在<template>元素上使用,也不能和v-else搭配使用。
3、v-if vs v-show
-
v-if是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建。 -
v-if也是惰性的:如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才被渲染。 -
相比之下,
v-show简单许多,元素无论初始条件如何,始终会被渲染,只有 CSSdisplay属性会被切换。 -
总的来说,
v-if有更高的切换开销(元素的有无),而v-show有更高的初始渲染开销(CSS改变)。因此,如果需要频繁切换,则使用v-show较好;如果在运行时绑定条件很少改变,则v-if会更合适。
7.4.4 v-for
v-for是Vue中的列表渲染指令,用于基于一个数组、对象或数字来循环渲染一个列表。
使用v-for基于数组渲染列表的语法格式如下:
<标签名 v-for= "(item, [index]) in arr"></标签名>
使用v-for基于对象渲染列表的语法格式如下:
<标签名 v-for = "(value, [key], [index]) in obj"></标签名>
使用v-for基于数字渲染列表的语法格式如下。
<标签名 v-for = "(item, [index]) in num"></标签名>
具体使用:
<template>
<div>
基于数组的渲染列表:
<!-- index表示索引,当然不是非得使用index这个单词 -->
<!-- 语法规范弱的条件下,:key不写也可以,推荐写,可以提高渲染性能 -->
<div v-for="(city, index) in cities" :key="index">
索引{{ index }} -> {{ city }}
</div>
基于对象的渲染列表:
<div v-for="(value, key) in person" :key="key">
{{ key }} -> {{ value }}
</div>
基于数值的渲染列表:
<div v-for="value in 5" :key="value">
{{ value }}
</div>
</div>
</template>
<script setup>
import {reactive} from "vue";
const cities = reactive(["北京", "上海", "广州", "深圳"])
const person = reactive({
id: 1001,
name: '张三',
age: 18
})
</script>
7.5 组件
7.5.1 组件的生命周期
在Vue中,组件的生命周期是指一个组件从被创建到被销毁的整个过程,这个过程包括组件的创建、挂载、更新、销毁四个主要阶段。在这些阶段中,Vue提供了一系列相应的生命周期钩子函数,它们会在对应的阶段自动执行。通过这些函数,开发者可以在某个特定的时机执行特定的逻辑。

常见钩子函数
- onMounted() 注册一个回调函数(钩子函数),在组件挂载完成后执行。
- onUpdated() 注册一个回调函数,在组件因为响应式状态变更而更新其 DOM 树之后调用。
- onUnmounted() 注册一个回调函数,在组件实例被卸载之后调用。
- onBeforeMount() 注册一个回调函数,在组件被挂载之前被调用。
- onBeforeUpdate() 注册一个回调函数,在组件即将因为响应式状态变更而更新其 DOM 树之前调用。
- onBeforeUnmount() 注册一个回调函数,在组件实例被卸载之前调用。
具体使用案例:
<template>
<div>
<span id="span1" v-text="message"></span> <br>
<input type="text" v-model="message">
</div>
</template>
<script setup>
import {ref, onMounted, onBeforeUpdate, onUpdated,} from 'vue'
let message = ref('hello')
// 在组件被挂载到DOM前执行
onMounted(() => {
console.log('===========onMounted===========')
const span1 = document.querySelector('#span1');
console.log(span1.innerHTML)
})
// 在组件即将因为响应式状态变更而更新其DOM之前执行
onBeforeUpdate(() => {
console.log('===========onBeforeUpdate===========')
const span1 = document.querySelector('#span1');
console.log(span1.innerHTML)
})
// 在组件因为响应式状态变更而更新其DOM之后执行
onUpdated(() => {
console.log('===========onUpdated===========')
const span1 = document.querySelector('#span1');
console.log(span1.innerHTML)
})
</script>
生命周期详解官方文档:组合式 API:生命周期钩子 | Vue.js
7.5.2 组件的注册
当在Vue项目中定义了一个新的组件后,要想在其他组件中引用这个组件,需要对这个组件进行注册。组件注册的方式有两种,分别是全局注册和局部注册。
1、全局注册
全局注册组件是指将一个组件注册到全局范围,使得该组件可以在当前项目的任何地方被引用。全局组件需要在main.js文件中通过Vue应用实例的component()方法进行注册,该方法的语法格式如下。
const app = createApp(App)
app.component('组件名称',需要引入的组件)
具体使用:
-
需要进行全局注册的组件
<template> <h1>{{ message }}, 我是通过全局注册的Vue组件</h1> </template> <script setup> import {ref} from 'vue' const message = ref('hello') </script> -
在main.js中进行全局注册
// 导入createApp()函数,用于创建Vue应用实例 import { createApp } from 'vue' import App from './components/App11Registry.vue' import GlobalComponent from './components/GlobalComponent.vue' const app = createApp(App) // 全局注册组件 app.component("GlobalComponent",GlobalComponent) app.mount('#app') -
使用全局注册的组件
<template> <div> <h1>{{ msg }}我是App11Registry组件</h1> <!--直接使用--> <GlobalComponent/> </div> </template> <script setup> import {ref} from "vue"; const msg = ref('Hi~') </script>
2、局部注册
局部注册是指在某个组件中注册另一个组件,被局部注册的组件只能在当前组件中使用。例如,在组件A中注册了组件B,则组件B只能在组件A中使用。
在选项式API中的局部注册:
<script>
import PartComponent from './PartComponent.vue'
export default {
components: {
'PartComponent': PartComponent
}
}
</script>
在组合式API中的局部注册(setup语法糖):
<template>
<PartComponent/>
</template>
<script setup>
import PartComponent from './PartComponent.vue'
</script>
导入的组件会被自动注册,无须手动进行注册,导入后可以直接在当前组件的模板中使用
7.5.3 组件的传递数据
在实际开发中,经常会遇到不同组件之间需要共享或传递一些数据。例如一个页面由导航栏组件和内容组件组成,当用户单击导航栏中的链接时,需要传递相应的数据到内容组件以展示相关的内容。
当一个组件中引入了其他组件时,当前组件被称为父组件,而引入的组件被称为子组件,父组件和子组件是一个相对的概念。父组件可以传递数据给子组件,子组件也可传递数据给父组件。
1、父组件向子组件传递数据
父组件向子组件传递数据可以通过props来实现。若要实现父组件向子组件传递数据,需要先在子组件中声明props,表示子组件可以从父组件中接收哪些数据。子组件在接收这些数据时,需要在其组件定义中显式声明这些属性,以便Vue能够正确地处理和验证这些传递过来的值。具体操作如下:
-
首先,在父组件中定义需要传递给子组件的值,接着,在父组件的模板中引入子组件,同时在引入子组件的标签中添加 props 属性并为其设置需要传递的值。
-
在 Vue3 中,父组件通过 props 传递给子组件的值是响应式的。也就是说,如果在父组件中的传递的值发生了改变,子组件中的值也会相应地更新。
-
在使用setup语法糖时,子组件声明props需要使用defineProps()函数来实现,
<script setup>
import {defineProps} from "vue";
defineProps(
{属性1: 类型},
{属性2: 类型},
……
)
</script>
<template>
<子组件名称 :属性1="数据1" :属性2="数据2" ……/>
</template>
<script setup>
//导入子组件
//定义数据
</script>
具体使用:
-
父组件代码:
<template> <div> <h2>我是父组件</h2> <button @click="changeMessage">点击更新</button> <!--使用子组件,并传递数据--> <App12Son :message="message" :count="count"/> </div> </template> <script setup> import App12Son from "@/components/App12Son.vue"; import {ref} from "vue"; let message = ref('你好') let count = ref(40) function changeMessage() { message.value = '修改数据' count.value++ } </script> -
子组件代码:
-
<template> <div> <h2>我是子组件</h2> <div> {{ message }}, {{ count }} </div> </div> </template> <script setup> import {defineProps} from "vue"; // 声明父组件传递属性值 defineProps({ message: String, count: Number }) </script>
2、子组件向父组件传递数据
在Vue中,子组件向父组件传递数据可以通过自定义事件来实现。在使用自定义事件时,需要在子组件中声明和触发自定义事件,在父组件中监听自定义事件。具体操作如下:
- 首先需要在子组件中使用defineEmits()函数声明该事件,语法格式如下。
<script setup>
const emit = defineEmits(['自定义事件名称'])
</script>
- 自定义事件声明完成后,通过emit()函数触发该事件,并将数据传递给父组件,语法格式如下。
emit('自定义事件名称','需要传递的数据')
- 父组件想要获取到子组件传递的数据,可以通过v-on来监听子组件抛出的事件,并对接收到的数据进行处理,监听子组件抛出事件的语法格式如下。
<子组件名称 @自定义事件名称="事件处理器" />
- 在上述语法格式中,当触发该自定义事件时,父组件会接收到子组件中传递的数据,在事件处理器中可以对该数据进行处理,语法格式如下。
<script setup>
const 方法名 = (数据) =>{
//处理接收到数据
}
</script>
具体使用:
-
子组件代码:
<template> <div> <h2>子组件</h2> <button @click="sendMsgToParentIncrease">数量+1发送给父组件</button> <button @click="sendMsgToParentDecrease">数量-1发送给父组件</button> </div> </template> <script setup> import {ref, defineEmits} from "vue"; const count = ref(1) // 1.定义要发送给父组件的方法,可以1或者多个 const emit = defineEmits(['increase', 'decrease']) function sendMsgToParentIncrease() { // 2.出发父组件对应的方法,调用defineEmits对应的属性 emit('increase', count.value++) } function sendMsgToParentDecrease() { emit('decrease', count.value--) } </script> -
父组件代码:
<template> <div> <h2>父组件,接收子组件的发送的数据:{{ pCount }}</h2> <!-- 声明@事件名应该等于子模块对应事件名!调用方法可以是当前自定义!--> <App13Son @increase="add" @decrease="sub"/> </div> </template> <script setup> import App13Son from "./App13Son.vue"; import {ref} from "vue"; let pCount = ref(0) //自定义接收,子组件传递数据方法! 参数为数据! function add(data) { console.log(data) pCount.value = data } function sub(data) { console.log(data) pCount.value = data } </script>
3、兄弟组件传参
思考:如何通过子传父,父传子,实现兄弟组件之间的数据传递?
7.6 Vue路由
在Vue项目中,主要通过单一的HTML页面集成多个组件来展示不同的功能。由于一个项目包含的组件众多,并且功能也各不相同,所以不会同时在一个页面上展示所有组件,而是希望通过单击链接或其他方式切换到对应功能的组件。为了解决这个问题,Vue提供了路由机制,它可以实现在不刷新页面的情况下切换不同的组件。
需求:

7.6.1 Vue Router
安装路由
npm install vue-router
准备页面组件
- App.vue
- Home.vue
- List.vue
使用路由:
-
新建router.js文件,创建路由实例并定义路由规则
创建路由实例是指初始化一个路由对象,该对象包含了所有关于路由的配置和逻辑。定义路由规则是指将URL映射到特定的组件上,当用户访问特定的URL时,路由会根据定义的路由规则来渲染对应的组件。在Vue中,使用createRouter()函数来创建路由实例。
// 导入路由创建的相关方法 import {createRouter, createWebHashHistory} from "vue-router"; // 导入vue组件 import Home from './components/App14BHome.vue' import List from './components/App14CList.vue' // 创建路由对象,声明路由规则 const router = createRouter({ //createWebHashHistory() 是 Vue.js 基于 hash 模式创建路由的工厂函数。在使用这种模式下,路由信息保存在 URL 的 hash 中 history: createWebHashHistory(), routes: [ { path: '/home', component: Home }, { path: '/list', component: List } ] }) // 导出路由对象 export default router -
在main.js文件中,导入并挂载路由实例
import { createApp } from 'vue'; import App from './components/App14ARouter.vue'; import router from './router'; const app = createApp(App); // 绑定路由对象 app.use(router); app.mount('#app'); -
在App.vue中定义路由链接和路由视图
为了在页面中将路由对应的组件显示出来,还需要在父组件中定义路由视图。路由视图使用标签定义,该标签会被渲染成当前路由对应的组件。另外,为了方便在不同组件之间切换,可以通过标签定义路由链接,该标签的to属性用于指定链接路径,与路由规则中path属性指定的URL对应。
<template> <div> <h2>App页面</h2> <hr/> <!-- 路由的连接 --> <router-link to="/home" style="padding-right: 16px">Home</router-link> <router-link to="/list">List</router-link> <!-- 路由连接对应视图的展示位置 --> <router-view></router-view> </div> </template>
路由重定向
重定向的作用:将一个路由重定向到另一个路由上
需求:修改案例:访问/list和/showAll都定向到List.vue
-
router.js
// 导入路由创建的相关方法 import {createRouter, createWebHashHistory} from "vue-router"; // 导入vue组件 import Home from './components/App14BHome.vue' import List from './components/App14CList.vue' // 创建路由对象,声明路由规则 const router = createRouter({ // //createWebHashHistory() 是 Vue.js 基于 hash 模式创建路由的工厂函数。在使用这种模式下,路由信息保存在 URL 的 hash 中 history: createWebHashHistory(), routes: [ { path: '/', component: Home }, { path: '/home', component: Home }, { path: '/list', component: List }, // 重定向 { path: '/showAll', redirect: '/list' } ] }) // 导出路由对象 export default router -
App.vue
<template> <div> <h2>App页面</h2> <hr/> <!-- 路由的连接 --> <router-link to="/home" style="padding-right: 16px">Home</router-link> <router-link to="/list" style="padding-right: 16px">List</router-link> <!-- 增加一个重定向的路由连接 --> <router-link to="/showAll">showAll</router-link> <!-- 路由连接对应视图的展示位置 --> <router-view></router-view> </div> </template>
7.6.2 路由传参
在实际开发中,经常需要在页面跳转时传递一些数据,例如从列表跳转到详情页时,需要传递选中项的ID以获取该项的详细内容,这时可以通过路由传参来实现。
Vue Router提供了两种传参方式,分别是通过params传递动态路径参数和通过query传递查询参数
1、通过params传递动态路径参数
通过params传递动态路径参数时,首先需要在路由规则配置文件(router.js)中指定这些参数。在路由规则中可以使用“:参数名”的方式指定动态路径参数,比如:
{path: '/showDetail/:param1/:param2',component: showDetail}
在路由规则中指定了动态路径参数后,可以在组件中使用<router-link>标签定义路由链接时指定这些参数的具体值,比如:
<router-link to="/showDetail/value1/value2">链接名称</router-link>
指定了动态路径参数的具体值后,可以在对应组件中获取这些参数的值。在获取参数值时需要用到**useRoute()**函数,该函数用于获取包含当前路由信息的对象,通过该对象的params值可以获取当前路由中指定的动态路径参数。
<script setup>
import {useRoute} from "vue-router";
const route = useRoute()
console.log(route.params.param1)
console.log(route.params.param2)
</script>
2、通过query传递查询参数
通过query传递查询参数时,路由规则配置文件中不需要预先指定这些参数,只需要定义问号“?”前面的路径即可,示例代码如下。
{path: '/showDetail',component: showDetail}
在组件中使用标签定义路由链接时,需要在URL路径后面附加查询参数,示例代码如下。
<router-link to="/showDetail?param1=value1¶m2=value2">链接名称</router-link>
在对应组件中,可以通过useRoute()函数获取包含当前路由信息的对象,并通过该对象的query值获取URL路径中的查询参数。获取查询参数的示例代码如下。
<script setup>
import {useRoute} from "vue-router";
const route = useRoute()
route.query.param1
route.query.param2
</script>
具体使用:
-
App.vue组件:
<template> <div> <h1>路由传参</h1> <router-link to="/detail1/1/张三">获取动态路径参数</router-link> <router-link to="/detail2?id=2&name=李四">获取查询参数</router-link> <hr> <router-view></router-view> </div> </template> -
两个路由组件:
<template> <h2>动态路径参数</h2> <p>学号:{{ userId }} 姓名:{{ userName }}</p> </template> <script setup> import {useRoute} from "vue-router"; import {ref} from "vue"; const userId = ref(0) const userName = ref("") const route = useRoute() userId.value = route.params.id userName.value = route.params.name </script><template> <h2>查询参数</h2> <p>学号:{{ id }} 姓名:{{ name }}</p> </template> <script setup> import {useRoute} from "vue-router"; import {ref} from "vue"; const id = ref(0) const name = ref("") const route = useRoute() id.value = route.query.id name.value = route.query.name </script> -
router.js路由配置文件:
// 导入路由创建的相关方法 import {createRouter, createWebHashHistory} from "vue-router"; // 导入vue组件 import DetailB from './components/App15BDetail.vue' import DetailC from './components/App15CDetail.vue' // 创建路由对象,声明路由规则 const router = createRouter({ // //createWebHashHistory() 是 Vue.js 基于 hash 模式创建路由的工厂函数。在使用这种模式下,路由信息保存在 URL 的 hash 中 history: createWebHashHistory(), routes: [ { path: '/detail1/:id/:name', component: DetailB }, { path: '/detail2', component: DetailC } ] }) // 导出路由对象 export default router
7.6.3 编程式路由
在Vue中,路由的跳转通常有两种主要方式,分别为声明式路由和编程式路由。其中,使用标签定义路由链接的方式属于声明式路由,前面已经介绍过。然而在某些情况下,可能需要通过JavaScript代码动态地控制路由的跳转,例如单击某个按钮时进行路由跳转,对此可以通过编程式路由实现。
编程式路由是先通过useRouter()函数获取全局路由实例,然后通过调用该实例的push()方法实现路由跳转。push()方法可以接收一个字符串路径作为参数,用于跳转到路由规则中与该路径对应的路由组件。
<template>
<button @click="toHome">去首页</button>
<router-view></router-view>
</template>
<script setup>
import {useRouter} from "vue-router"
//获取全局路由实例
const router = useRouter()
//实现路由跳转
const toHome = () => {
router.push('/home')
}
</script>
编程式路由跳转时,如果需要传递参数,可以在push()方法中传递一个描述路由信息的对象作为参数,该对象可以包含路由的路径(path)、路由名称(name)、查询参数(query)和动态路径参数(params)等属性。其中,路由名称(name)是指在定义路由规则时为路由指定的一个唯一标识符(router.js),具体示例如下。
{path: '/pathA', name: 'componentA', component: ComponentA},
当指定路由名称后,可以在编程式路由中通过路由名称引用对应的路由。编程式路由传参的示例如下。
//传递动态路径参数(方式一)
router.push({ name: 'componentA', params: {id: 1, name: '张三'} })
//传递动态路径参数(方式二)
router.push({ path: '/pathA/1/张三'})
//传递查询参数
router.push({ path: '/pathA', query: {id : 1, name: '张三'} })
具体使用:
-
修改App.vue代码:
<template> <div> <h1>路由传参</h1> <button @click="toPage">编程式路由跳转</button> <hr> <router-view></router-view> </div> </template> <script setup> import {useRouter} from "vue-router"; const router = useRouter() const toPage = () => { router.push({ path: '/detail2', query: { id: 4, name: '赵六' } }) } </script>
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)