如何在Vue中用事件创建用户互动

作者选择 “开放性精神疾病“作为 “为国家而写“计划的一部分来接受捐赠。

简介

Vue.js开发中,客户的网络浏览器读取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)

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
复制代码

接下来,在src 目录中建立一个data 目录。

mkdir src/data
复制代码

在你选择的文本编辑器中,打开一个名为src/data/airports.js 的文件。在该文件中添加以下数据。

favorite-airports/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 文件。

为了渲染数据,创建一个名为src/components/AirportCard.vue 的单文件组件(SFC),并在你的文本编辑器中打开它。这个组件将包含机场卡的所有样式和逻辑。

在该文件中添加以下内容。

favorite-airports/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>
复制代码

这个组件包含一个_道具_,在Vue.js中,它是一种将数据从父组件向下传递到子组件的方式。template 部分然后渲染这些数据。关于单文件组件的更多信息,请查看《如何用Vue单文件组件创建可重复使用的代码块》教程。

你可能会注意到,代码片段中包含了一些CSS。在AirportCard.vue 组件中,包装器<div> 包含airport 的类。这个CSS通过添加边框给生成的HTML添加了一些样式,使每个机场看起来像一张卡片。:first-child:last-child 是_伪选择器_,对HTML中的第一个和最后一个p 标签应用不同的样式,其中div 的类为airport

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

接下来,修改现有的App.vue 组件,以遍历airports.js 数据并渲染一系列的AirportCards.vue 组件。在你的文本编辑器中打开src/App.vue ,用以下突出显示的代码替换其中的内容。

favorite-airports/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 ,发现以下内容。

A view of the airport data rendered on cards, with the airport abbreviation, full name, and location rendered in black, sans-serif font.

现在你已经设置好了你的示例项目,接下来你将使用v-on 指令探索内置事件。当该事件被触发时,将出现一个弹出式警报框,显示与该事件相关的机场的代码。

第2步–使用v-on 指令监听事件

如前所述,当用户与DOM(文档对象模型)中的HTML元素交互时,事件是一种执行功能的方式。在编写虚构的JavaScript时,为了在事件中执行一个函数,你可以编写一个叫做_事件监听器_的东西。事件监听器是一个等待互动发生的函数,然后执行一些代码。然而,在Vue中,你可以使用v-on _指令_来达到这个目的。指令是一段可重复使用的代码,开发者可以用它来操作DOM。Vue.js开箱即提供了v-on 指令。

在这一步,你将在你的应用程序中创建一个函数,当用户点击卡片时运行。在你选择的文本编辑器中打开src/components/AirportCard.vue 组件。

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

favorite-airports/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,它可以在<template> 中执行selectAirport 函数。

定义好函数后,你现在要把它附加到一个HTML元素的事件上。如前所述,你可以使用v-on 指令并附加一个名称为click 的事件;这是一个由Vue.js提供的事件。在AirportCard.vue 组件中,将v-on 指令添加到封装器<div>

favorite-airports/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 site with alert pop-up that reads "localhost:8080 says You clicked on CVG. It's located in Hebron, KY."

click 事件不是Vue.js为你提供的唯一开箱即用的事件。事实上,你可以使用v-on 任何本地的JavaScript事件,比如。

  • keyup
  • mouseover
  • focus
  • mouseenter
  • change

接下来,你将把这个v-on:click 监听器改为mouseover ,以说明Vue.js是如何监听事件的。mouseover 是一个只要鼠标指针移到HTML元素上就会触发的事件。

再次打开src/components/AirportCard.vue ,用下面的高亮代码更新你的文件。

favorite-airports/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 ,并在一个卡片上悬停时,该函数将执行并显示一个本地警报。

这个功能对于测试来说是很好的,但可能是不受欢迎的,因为每次用户悬停在它上面都会显示警报。一个更好的体验可能是只在用户第一次悬停在该卡片上时显示它。在vanilla JavaScript中,你可以跟踪用户在一个卡片上停留的次数,然后防止进一步执行。Vue.js有_事件修改器_,你可以利用它来完成同样的事情,而且代码更少。

在下一节中,你将探索事件修改器并使用它们来获得更好的用户体验。

第3步 – 使用事件和键修改器

在上一节中,你执行了一个关于clickmouseover 事件的函数。你还了解了Vue.js对v-on 事件的速记方法。现在你将在此基础上进一步扩展,给这个mouseover 事件附加一个修改器,这样你的函数就只执行一次。

Vue.js为你提供了大量的事件修改器。其中一些包括。

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

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

favorite-airports/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 。在接下来的部分,想象一下你想让这个点击动作更明确一些。一种方法是在模板中的.airport <div> 上为@click 事件添加一个按键修改器。

要做到这一点,将@mouseover 改为@click ,并添加.shift 修改器。

favorite-airports/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中开发应用程序时,有时你需要通过自定义事件将数据上传到父组件。道具是只读的数据,从父组件传给子组件,但通过$emit 的自定义动作则与此相反。为了创建最可重复使用的组件,最好把这些看作是函数。你通过props(参数)向下传递数据,并向父代发射值(return 值)。

为了从子组件向父组件发射一个事件,你可以使用$emit 函数。在实现这个功能之前,本教程将引导你通过一个例子来演示如何工作。

$emit 函数接受两个参数:动作名称(一个字符串),以及要传递给父组件的值。在下面的例子中,当用户点击按钮时,你将把值CVG 发送给动作favoriteAirport 下的父组件。

ChildComponent.vue

<template>
  <button @click="$emit('favoriteAirport', 'CVG')">A button</button>
</template>
复制代码

在父组件中,你将使用v-on 指令并监听favoriteAirport 事件。当这个自定义事件被触发时,代码将对该值做一些处理。

ParentComponent.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) 取代它。记住,第一个rugment是事件的名称,第二个是你要发射的值。

favorite-airports/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。你将在已经存在的六个卡片之后显示最喜欢的机场列表。

favorite-airports/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 事件。

favorite-airports/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 。当你点击其中一个机场卡时,该卡就会出现在喜爱的机场下。

Vue airport app with a list of favorite airports that includes the CVG airport card.

在本节中,你了解了自定义事件,它们是什么,以及如何使用它们。自定义事件是一种通过Vue提供的$emit 函数将数据向上传递到父组件的方式。一旦这些数据被发射出去,你就可以在父组件中进一步操作它,比如把它添加到一个数组中。

总结

在本教程中,你学到了Vue.js如何监听一些内置事件,如clickmouseover 。除此之外,你还尝试了事件和关键修饰符,即附加在事件上的小段代码,以提供额外功能。有了这个,你设置了你的应用程序,用.once 修改器执行一次函数,而用.shift 修改器只在按住SHIFT 键时发射。

Vue提供了一种有效的方法来监听事件,让你专注于操作数据而不是手动设置事件监听器。除此之外,Vue允许你把组件看作是函数。它们接受数据props ,并可以用$emit ,返回一个值。

要了解更多关于Vue组件的信息,建议通读Vue文档。关于Vue的更多教程,请查看How To Develop Websites with Vue.js系列页面

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享