作者选择Open Sourcing Mental Illness接受捐赠,作为Write for DOnations计划的一部分。
介绍
在Vue.js开发中,客户端的 Web 浏览器读取 HTML 和JavaScript,并根据开发人员为其编写的指令呈现网页。但是网页或应用程序不仅需要处理数据;它还需要处理用户交互。为此,开发人员使用JavaScript中的事件在用户与HTML元素交互时执行代码。
事件可以捕获任何用户与用户界面按钮或物理键盘或鼠标的交互。在 JavaScript 中,您将创建事件侦听器,等待该事件发生,然后执行代码块。在 Vue.js 中,你不需要监听事件;这是使用v-on:
指令自动完成的。
在本教程中,您将使用 Vue 中的事件来创建机场代码的应用程序。当用户选择机场代码时,应用程序会将该机场添加到“收藏夹”集合中。通过跟随这个项目,您将了解什么是事件、如何使用 Vue 的内置事件以及如何创建自己的自定义事件。
先决条件
要完成本教程,您需要:
14.17.0
您的计算机上安装了Node.js 版本或更高版本。要在 macOS 或 Ubuntu 20.04 上安装它,请按照如何在 macOS 上安装 Node.js 和创建本地开发环境或如何在 Ubuntu 20.04 上安装 Node.js 的使用 PPA 安装部分中的步骤进行操作。- Vue的CLI您的计算机上安装按照步骤1中如何产生Vue.js单页应用程序会与Vue的CLI。在本教程的第一步中,您将使用它来创建您的 Vue 应用程序。
- 您还需要具备 JavaScript、HTML 和 CSS 的基本知识,您可以在我们的如何使用 HTML 构建网站系列、如何使用 CSS 构建网站系列和如何使用 JavaScript 编码中找到这些知识。
步骤 1 — 设置项目
本教程的第一步是设置一个演示项目,其中包含一些要在视图中显示的数据。这将包括一个包含机场数据的JavaScript 对象数组和一个用于迭代和呈现数据的 Vue组件。
首先,使用 Vue CLI 生成一个项目:
- vue create favorite-airports
这将创建一个名为favorite-airports
. 本教程将使用 Vue 3,因此在出现提示时,选择选项Default (Vue 3) ([Vue 3] babel, eslint)
:
OutputVue CLI v4.5.6
? Please pick a preset:
Default ([Vue 2] babel, eslint)
❯ Default (Vue 3) ([Vue 3] babel, eslint)
Manually select features
创建项目后,创建一个目录来保存该项目的所有本地数据。首先,将新项目文件夹设为您的工作目录:
- cd favorite-airports
接下来,在data
目录中创建一个src
目录:
- mkdir src/data
在您选择的文本编辑器中,打开一个名为src/data/airports.js
. 将以下数据添加到文件中:
export default [
{
name: 'Cincinnati/Northern Kentucky International Airport',
abbreviation: 'CVG',
city: 'Hebron',
state: 'KY',
},
{
name: 'Seattle-Tacoma International Airport',
abbreviation: 'SEA',
city: 'Seattle',
state: 'WA',
},
{
name: 'Minneapolis-Saint Paul International Airport',
abbreviation: 'MSP',
city: 'Bloomington',
state: 'MN',
},
{
name: 'Louis Armstrong New Orleans International Airport',
abbreviation: 'MSY',
city: 'New Orleans',
state: 'LA',
},
{
name: `Chicago O'hare International Airport`,
abbreviation: 'ORD',
city: 'Chicago',
state: 'IL',
},
{
name: `Miami International Airport`,
abbreviation: 'MIA',
city: 'Miami',
state: 'FL',
}
]
该数据是由美国几个机场组成的对象数组。接下来,你通过这个数据去重复,以产生由该卡name
,abbreviation
,city
,和state
属性。当用户点击卡片时,应用程序将向父级发出一个事件,该事件将该机场添加到代表您最喜欢的机场的数据集合中。
保存并关闭airport.js
文件。
要呈现数据,请使用名称创建单文件组件 (SFC)src/components/AirportCard.vue
并在文本编辑器中打开它。该组件将包含机场卡的所有样式和逻辑。
将以下内容添加到文件中:
<template>
<div class="airport">
<p>{{ airport.abbreviation }}</p>
<p>{{ airport.name }}</p>
<p>{{ airport.city }}, {{ airport.state }}</p>
</div>
</template>
<script>
export default {
props: {
airport: {
type: Object,
required: true
}
}
}
</script>
<style scoped>
.airport {
border: 3px solid;
border-radius: .5rem;
padding: 1rem;
}
.airport p:first-child {
font-weight: bold;
font-size: 2.5rem;
margin: 1rem 0;
}
.airport p:last-child {
font-style: italic;
font-size: .8rem;
}
</style>
该组件包含一个prop,它在 Vue.js 中是一种将数据从父组件向下传递到子组件的方法。template
然后该部分呈现此数据。有关单文件组件的更多信息,请查看如何使用 Vue 单文件组件教程创建可重用的代码块。
您可能会注意到代码片段中包含一些CSS。在AirportCard.vue
组件中,包装器<div>
包含airport
. 此 CSS 通过添加边框为每个机场提供卡片外观,从而为生成的 HTML 添加一些样式。:first-child
和:last-child
是伪选择器,它们将不同的样式应用于p
HTML 中的第一个和最后一个标签,div
类为airport
.
保存文件并退出文本编辑器。
接下来,修改现有App.vue
组件以遍历airports.js
数据并渲染一系列AirportCards.vue
组件。src/App.vue
在文本编辑器中打开并用以下突出显示的代码替换内容:
<template>
<div class="wrapper">
<div v-for="airport in airports" :key="airport.abbreviation">
<airport-card :airport="airport" />
</div>
</div>
</template>
<script>
import { ref } from 'vue'
import allAirports from '@/data/airports.js'
import AirportCard from '@/components/AirportCard.vue'
export default {
components: {
AirportCard
},
setup() {
const airports = ref(allAirports)
return { airports }
}
}
</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;
}
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-column-gap: 1rem;
max-width: 960px;
margin: 0 auto;
}
</style>
这会导入数据和 SFC,然后使用v-for
指令迭代数据,为airport.js
数组中的每个对象创建一个机场卡。它还为wrapper
该类添加了额外的 CSS,该类使用CSS 网格来管理卡片的布局。
保存并退出文件。现在设置项目后,使用以下命令运行本地开发服务器:
- npm run serve
这将在您的localhost
,通常在端口上启动一个服务器:8080
。打开您选择的网络浏览器并访问localhost:8080
以查找以下内容:
现在您已经设置了示例项目,接下来您将使用该v-on
指令探索内置事件。触发此事件时,将出现一个警告弹出框,其中包含与该事件关联的机场的机场代码。
第 2 步 – 使用v-on
指令监听事件
如前所述,当用户与DOM(文档对象模型)中的 HTML 元素交互时,事件是执行功能的一种方式。在编写原生 JavaScript 时,要对事件执行函数,您可以编写称为事件侦听器的东西。事件侦听器是一个等待交互发生的函数,然后执行一些代码。但是,使用 Vue,您可以为此目的使用该v-on
指令。指令是一段可重复使用的代码,开发人员可以使用它来操作 DOM。该v-on
指令由 Vue.js 开箱即用。
在这一步中,您将在您的应用程序中创建一个函数,当用户单击卡片时运行该函数。src/components/AirportCard.vue
在您选择的文本编辑器中打开组件。
创建一个函数,通过添加以下突出显示的代码来提醒用户他们点击了机场:
...
<script>
export default {
props: {
airport: {
type: Object,
required: true
}
},
setup() {
function selectAirport(airport) {
alert(`You clicked on ${airport.abbreviation}. It's located in ${airport.city}, ${airport.state}.`)
}
return { selectAirport }
}
}
</script>
...
在 Vue.js 3 中,需要在setup
组件方法中定义和导出响应式函数。这告诉Vue公司,它可以执行selectAirport
的功能<template>
。
定义函数后,您现在将它附加到 HTML 元素上的事件。如前所述,您可以使用该v-on
指令并附加一个名为click
;的事件。这是 Vue.js 提供的事件。在AirportCard.vue
组件中,将v-on
指令添加到包装器<div>
:
<template>
<div class="airport" v-on:click="selectAirport(airport)">
<p>{{ airport.abbreviation }}</p>
<p>{{ airport.name }}</p>
<p>{{ airport.city }}, {{ airport.state }}</p>
</div>
</template>
...
添加此代码后,保存并退出文件。
现在,当您单击卡片时,会弹出带有所提供消息的警报。CVG
例如,如果您单击,您会发现以下内容:
该click
事件并不是 Vue.js 开箱即用的唯一事件。实际上,您可以使用v-on
任何原生 JavaScript 事件,例如:
keyup
mouseover
focus
mouseenter
change
接下来,您将更改此v-on:click
侦听器mouseover
以说明 Vue.js 如何侦听事件。mouseover
是当鼠标光标移动到 HTML 元素上时触发的事件。
src/components/AirportCard.vue
再次打开并使用以下突出显示的代码更新您的文件:
<template>
<div class="airport" @mouseover="selectAirport(airport)">
<p>{{ airport.abbreviation }}</p>
<p>{{ airport.name }}</p>
<p>{{ airport.city }}, {{ airport.state }}</p>
</div>
</template>
如此处所示,Vue 还具有v-on:
事件的速记语法。要使用速记语法,请替换v-on
为@
. 保存并退出文件。
现在,当您访问localhost:8080
卡片并将鼠标悬停在卡片上时,该功能将执行并显示本机警报。
此功能适用于测试目的,但可能不受欢迎,因为每次用户将鼠标悬停在其上方时都会显示警报。更好的体验可能是仅在用户第一次将鼠标悬停在该卡片上时才显示它。在原生 JavaScript 中,您可以跟踪用户将鼠标悬停在卡片上的次数,然后阻止进一步执行。Vue.js 具有事件修饰符,您可以利用它们以更少的代码完成相同的事情。
在下一节中,您将探索事件修饰符并使用它们来获得更好的用户体验。
第 3 步 – 使用事件和键修饰符
在上一节中,您对click
和mouseover
事件执行了一个函数。您还了解了 Vue.jsv-on
事件的简写。现在,您将通过将修饰符附加到此mouseover
事件来进一步扩展此事件,以便您的函数仅执行一次。
Vue.js 为您提供了许多事件修饰符。其中一些包括:
.stop
: 停止事件传播.prevent
: 阻止 HTML 元素的默认行为.capture
: 处理针对选定元素之前的内部元素的事件.self
: 如果event.target
是元素本身,则仅触发处理程序.once
: 只执行一次函数.passive
: 使元素的默认行为立即发生而不是等待事件,这可用于优化移动设备上滚动的性能
在这种情况下,您将使用.once
修饰符。在文本编辑器中,打开AirportCard.vue
组件并将修饰符添加到现有mouseover
事件:
<template>
<div class="airport" @mouseover.once="selectAirport(airport)">
<p>{{ airport.abbreviation }}</p>
<p>{{ airport.name }}</p>
<p>{{ airport.city }}, {{ airport.state }}</p>
</div>
</template>
保存文件。在浏览器中访问您的应用程序,您会发现该事件仅在第一个mouseover
事件上触发一次。
接下来,您将通过使用键修饰符继续探索修饰符。这些键修饰符与击键事件相关联,例如keyup
. 对于下一部分,假设您想让这个点击动作更明确一些。一种方法是向模板中的@click
事件添加键修饰符.airport
<div>
。
为此,请更改@mouseover
为@click
并添加.shift
修饰符:
<template>
<div class="airport" @click.shift="selectAirport(airport)">
<p>{{ airport.abbreviation }}</p>
<p>{{ airport.name }}</p>
<p>{{ airport.city }}, {{ airport.state }}</p>
</div>
</template>
保存更改并在浏览器中打开应用程序。如果您在不按住SHIFT
钥匙的情况下单击卡片,警报将不会执行任何操作。现在,尝试SHIFT
在单击卡片时按住该键。您的函数现在将执行,您将收到警报。
在本节中,您了解了 Vue 的内置事件以及与这些事件关联的修饰符。您可以使用这些内置事件完成很多工作,但有时您需要自定义事件。在下一节中,您将使用自定义事件向父级发出一个动作,以便它执行一个函数。
第 4 步 – 创建自定义事件
在 Vue.js 中开发应用程序时,有时需要通过自定义事件将数据向上传递给父组件。道具是从父级传递给子级的只读数据,但通过 an 的自定义操作与$emit
此相反。要创建最可重用的组件,最好将它们视为函数。您通过道具(参数)向下传递数据,并将值发送回父级(一个return
值)。
要从子组件向父组件发出事件,请使用该$emit
函数。在实施之前,本教程将指导您通过一个示例来演示它是如何工作的。
该$emit
函数接受两个参数:操作名称(字符串)和要传递给父级的值。在以下示例中,当用户单击按钮时,您将值发送CVG
到 action 下的父组件favoriteAirport
:
<template>
<button @click="$emit('favoriteAirport', 'CVG')">A button</button>
</template>
在父组件中,您将使用v-on
指令并侦听favoriteAirport
事件。当这个自定义事件被触发时,代码会对这个值做一些事情:
<template>
<child-component @favoriteAirport="favoriteAirport = $event" />
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const favoriteAirport = ref('')
return { favoriteAirport }
}
}
</script>
该事件的价值将是$event
。在这种情况下,$event
实际上是CVG
,然后将其存储在名为 的反应式数据属性中favoriteAirport
。
既然您知道自定义事件是什么样的,您将通过在您的应用程序中实现这个自定义事件来将其付诸实践。
AirportCards.vue
在文本编辑器中打开组件。在这种情况@click
下,删除对该函数的引用并将其替换为$emit("favoriteAirport", airport)
. 请记住,第一个参数是事件的名称,第二个参数是您发出的值:
<template>
<div class="airport" @click="$emit('favoriteAirport', airport)">
<p>{{ airport.abbreviation }}</p>
<p>{{ airport.name }}</p>
<p>{{ airport.city }}, {{ airport.state }}</p>
</div>
</template>
...
保存文件。现在,当用户点击机场卡时,一个自定义事件将触发并传递该airport
对象。
接下来,打开src/App.vue
以向模板添加一些 HTML。您将在已经存在的六张卡片之后显示最喜欢的机场列表:
<template>
<div class="wrapper">
<div v-for="airport in airports" :key="airport.abbreviation">
<airport-card :airport="airport" />
</div>
<h1 v-if="favoriteAirports.length">Favorite Airports</h1>
<div v-for="airport in favoriteAirports" :key="airport.abbreviation">
<airport-card :airport="airport" />
</div>
</div>
</template>
<script>
import { ref } from 'vue'
import allAirports from '@/data/airports.js'
import AirportCard from '@/components/AirportCard.vue'
export default {
components: {
AirportCard
},
setup() {
const airports = ref(allAirports)
const favoriteAirports = ref([])
return { airports, favoriteAirports }
}
}
</script>
...
在此代码片段中,您将创建一个名为 的反应式数据属性favoriteAirports
,它是一个空数组。在 中<template>
,您遍历空数组以呈现<airport-card />
组件,就像您在前面的步骤中所做的那样。
现在您需要v-on
为您的自定义事件添加事件:
<template>
<div class="wrapper">
<div v-for="airport in airports" :key="airport.abbreviation">
<airport-card :airport="airport" @favoriteAirport="favoriteAirports.push($event)" />
</div>
<h1 v-if="favoriteAirports.length">Favorite Airports</h1>
<div v-for="airport in favoriteAirports" :key="airport.abbreviation">
<airport-card :airport="airport" />
</div>
</div>
</template>
...
在@favoriteAiport
自定义事件中,您使用 JavaScriptpush()
方法将机场从子 ( $event
) 添加到favoriteAirports
反应数据属性。
打开浏览器并导航到您的项目localhost:8080
。当您单击其中一张机场卡时,该卡将显示在“最喜欢的机场”下。
在本节中,您了解了自定义事件、它们是什么以及如何使用它们。自定义事件是一种$emit
通过 Vue 提供的函数将数据向上传递给父组件的方式。数据发出后,您可以在父组件中进一步操作它,例如将其添加到数组中。
结论
在本教程中,您学习了 Vue.js 如何侦听许多内置事件,例如click
和mouseover
。除此之外,您还尝试了事件和键修饰符,即附加到事件中以提供附加功能的一小段代码。有了这个,您将应用程序设置为使用.once
修饰符执行一次函数,并且仅在SHIFT
使用.shift
修饰符按住键时触发。
Vue 提供了一种有效的事件监听方式,让您可以专注于操作数据而不是手动设置事件监听器。除此之外,Vue 允许您将组件视为函数:它们接受数据props
并可以返回一个带有$emit
.
要了解有关 Vue 组件的更多信息,建议通读Vue 文档。有关 Vue 的更多教程,请查看如何使用 Vue.js 系列页面开发网站。