如何在 Vue 中创建用户与事件的交互

作者选择Open Sourcing Mental Illness接受捐赠,作为Write for DOnations计划的一部分。

介绍

Vue.js开发中,客户端的 Web 浏览器读取 HTML 和JavaScript,并根据开发人员为其编写的指令呈现网页。但是网页或应用程序不仅需要处理数据;它还需要处理用户交互。为此,开发人员使用JavaScript中的事件用户与HTML元素交互时执行代码

事件可以捕获任何用户与用户界面按钮或物理键盘或鼠标的交互。在 JavaScript 中,您将创建事件侦听器,等待该事件发生,然后执行代码块。在 Vue.js 中,你不需要监听事件;这是使用v-on:指令自动完成的

在本教程中,您将使用 Vue 中的事件来创建机场代码的应用程序。当用户选择机场代码时,应用程序会将该机场添加到“收藏夹”集合中。通过跟随这个项目,您将了解什么是事件、如何使用 Vue 的内置事件以及如何创建自己的自定义事件。

先决条件

要完成本教程,您需要:

步骤 1 — 设置项目

本教程的第一步是设置一个演示项目,其中包含一些要在视图中显示的数据。这将包括一个包含机场数据JavaScript 对象数组和一个用于迭代和呈现数据的 Vue组件

首先,使用 Vue CLI 生成一个项目:

  • vue create favorite-airports

这将创建一个名为favorite-airports. 本教程将使用 Vue 3,因此在出现提示时,选择选项Default (Vue 3) ([Vue 3] babel, eslint)

Output
Vue 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. 将以下数据添加到文件中:

最喜欢的机场/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',
  }
]

该数据是由美国几个机场组成的对象数组。接下来,你通过这个数据去重复,以产生由该卡nameabbreviationcity,和state属性。当用户点击卡片时,应用程序将向父级发出一个事件,该事件将该机场添加到代表您最喜欢的机场的数据集合中。

保存并关闭airport.js文件。

要呈现数据,请使用名称创建单文件组件 (SFC)src/components/AirportCard.vue并在文本编辑器中打开它。该组件将包含机场卡的所有样式和逻辑。

将以下内容添加到文件中:

最喜欢的机场/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 单文件组件教程创建可重用的代码块

您可能会注意到代码片段中包含一些CSSAirportCard.vue组件中,包装器<div>包含airport. 此 CSS 通过添加边框为每个机场提供卡片外观,从而为生成的 HTML 添加一些样式。:first-child:last-child伪选择器,它们将不同的样式应用于pHTML 中的第一个和最后一个标签,div类为airport.

保存文件并退出文本编辑器。

接下来,修改现有App.vue组件以遍历airports.js数据并渲染一系列AirportCards.vue组件。src/App.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在您选择的文本编辑器中打开组件。

创建一个函数,通过添加以下突出显示的代码来提醒用户他们点击了机场:

最喜欢的机场/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>

最喜欢的机场/src/components/AirportCard.vue
<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例如,如果您单击,您会发现以下内容:

带有警告弹出窗口的 Vue 站点,上面写着“localhost:8080 说你点击了 CVG。它位于肯塔基州希伯伦。”

click事件并不是 Vue.js 开箱即用的唯一事件。实际上,您可以使用v-on任何原生 JavaScript 事件,例如:

  • keyup
  • mouseover
  • focus
  • mouseenter
  • change

接下来,您将更改此v-on:click侦听器mouseover以说明 Vue.js 如何侦听事件。mouseover是当鼠标光标移动到 HTML 元素上时触发的事件。

src/components/AirportCard.vue再次打开并使用以下突出显示的代码更新您的文件:

最喜欢的机场/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 步 – 使用事件和键修饰符

在上一节中,您对clickmouseover事件执行了一个函数您还了解了 Vue.jsv-on事件的简写现在,您将通过将修饰符附加到此mouseover事件来进一步扩展此事件,以便您的函数仅执行一次。

Vue.js 为您提供了许多事件修饰符。其中一些包括:

  • .stop: 停止事件传播
  • .prevent: 阻止 HTML 元素的默认行为
  • .capture: 处理针对选定元素之前的内部元素的事件
  • .self: 如果event.target是元素本身,则仅触发处理程序
  • .once: 只执行一次函数
  • .passive: 使元素的默认行为立即发生而不是等待事件,这可用于优化移动设备上滚动的性能

在这种情况下,您将使用.once修饰符。在文本编辑器中,打开AirportCard.vue组件并将修饰符添加到现有mouseover事件:

最喜欢的机场/src/components/AirportCard.vue
<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修饰符:

最喜欢的机场/src/components/AirportCard.vue
<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

子组件.vue
<template>
  <button @click="$emit('favoriteAirport', 'CVG')">A button</button>
</template>

在父组件中,您将使用v-on指令并侦听favoriteAirport事件。当这个自定义事件被触发时,代码会对这个值做一些事情:

父组件.vue
<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). 请记住,第一个参数是事件的名称,第二个参数是您发出的值:

最喜欢的机场/src/components/AirportCard.vue
<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。您将在已经存在的六张卡片之后显示最喜欢的机场列表:

最喜欢的机场/src/App.vue
<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为您的自定义事件添加事件:

最喜欢的机场/src/App.vue
<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当您单击其中一张机场卡时,该卡将显示在“最喜欢的机场”下

包含 CVG 机场卡的最喜欢机场列表的 Vue 机场应用程序。

在本节中,您了解了自定义事件、它们是什么以及如何使用它们。自定义事件是一种$emit通过 Vue 提供函数将数据向上传递给父组件的方式数据发出后,您可以在父组件中进一步操作它,例如将其添加到数组中。

结论

在本教程中,您学习了 Vue.js 如何侦听许多内置事件,例如clickmouseover除此之外,您还尝试了事件和键修饰符,即附加到事件中以提供附加功能的一小段代码。有了这个,您将应用程序设置为使用.once修饰符执行一次函数,并且仅在SHIFT使用.shift修饰符按住时触发

Vue 提供了一种有效的事件监听方式,让您可以专注于操作数据而不是手动设置事件监听器。除此之外,Vue 允许您将组件视为函数:它们接受数据props并可以返回一个带有$emit.

要了解有关 Vue 组件的更多信息,建议通读Vue 文档有关 Vue 的更多教程,请查看如何使用 Vue.js 系列页面开发网站

觉得文章有用?

点个广告表达一下你的爱意吧 !😁