跳到主要内容位置

Vue 3 事件与响应性入门

张旭乾

到现在,我们把 Vue 基本的展示逻辑介绍完了,覆盖了常见的场景:

  • 在开合标签内引用 data 里的数据。
  • 在标签属性中引用 data 的数据。
  • 展示列表数据。
  • 根据条件展示数据。

不过,这些都是静态的展示,没有数据的变化,体现不了 vue 的优点。这篇文章我们将通过处理 html DOM 事件,来修改 data 里的数据,并看到页面根据 data 的变化而变化,也就是 vue 的响应性机制。

注册事件

我们先看一下怎么在 vue 项目中注册事件。在 vue 中注册事件,使用 v-on 加上冒号:后面跟上事件的名字:

<button v-on:click=""></button>

这里事件的名字,就是普通 html 事件,去掉 on 剩余的部分,常见的事件名可以查看这个表格:

HTML 事件名Vue 事件名
onclickclick
onchangechange
onblurblur
onfocusfocus
onsubmitsubmit
onresetreset

因为注册事件也是前端开发中经常要用到的功能,所以 v-on 也提供了简写形式,使用一个 "@" 符号,这个时候就不需要加冒号了:

<button @click=""></button>

事件处理

在事件处理的时候,可以给事件监听传递一个函数,或者直接使用 JavaScript 表达式,但是现在我们还没接触到在 vue 中如何定义函数/方法(methods),所以我们就用简单的 JavaScript 表达式来处理事件。 在事件处理代码中,可以直接访问和修改 data 中的属性,这段代码把 data 中,布尔类型的 showAnswer 属性进行了 toggle 操作,也就是每次点击按钮的时候,把 true 和 false 进行取反操作,用于切换 showAnswer 的 true 和 false 值,:

<button v-on:click="showAnswer = !showAnswer"></button>

data() { return { showAnswer: false, }; }

这时,事件的操作会修改 data 中 showAnswer 的值。如果这个时候,在 html 模板中有其它使用到 showAnswer 属性的地方,例如在一个标签的 v-show 中,根据它的值来判断是不是要显示这个标签,那么在 showAnswer 变化的时候,v-show 的判断也会动态变化,当 showAnswer 的值变为 true 时,这个标签就会渲染到 html 中,如果为 false 则不会,这个就是 vue 响应性机制的体现:

<p v-show="showAnswer" class="answer">
答:Vue 是一套用于构建用户界面的渐进式框架。
</p>

示例

好,我们来实际运行一下这个示例。假设我们要做一个 Q&A 问答卡片:

  • 卡片一开始只显示问题,和显示答案按钮。
  • 当点击显示答案时,在问题的下方展示答案,而显示答案按钮的文案变成隐藏答案。

我们来看一下实现过程。首先在我们的 vue 模板项目中,打开 index.js 文件,在 data() 函数返回的对象中,定义一个 showAnswer 属性,默认为 false,即不显示答案:

// 示例:事件处理和响应性入门
const app = Vue.createApp({
data() {
return {
showAnswer: false,
};
},
});
app.mount("#app");

接着,打开 index.html,在里边定义卡片的结构:

<div class="question">
<p>问:Vue 是一个什么样的框架?</p>
<p class="answer">答:Vue 是一套用于构建用户界面的渐进式框架。</p>
<button>显示答案</button>
</div>

这里:

  • 使用一个 div 来定义卡片的容器。
  • 在容器里边,使用一个 p 元素来显示一个问题。
  • 再在它的下边,使用另一个 p 元素来显示答案。
  • 最后,定义一个 button 元素,用于显示/隐藏答案。

现在这个页面是静态的,我们给按钮添加一个点击事件,让它在点击的时候,让 showAnwser 在 true 和 false 之间来回切换。这里:

  • 我们使用 v-on 的简写形式注册了 click 点击事件。
  • 之后给它设置处理代码,就是把 showAnswer 的值进行取反操作,并把结果再更新到 showAnswer 里。
<button @click="showAnswer = !showAnswer">显示答案</button>

接着,我们给存放答案的 p 元素,加上一个 v-show 指令,让它根据 showAnswer 的值,来决定是否要显示答案,如果 showAnswer 的值为 true 就显示答案,如果为 false 就隐藏答案:

<p v-show="showAnswer" class="answer">
答:Vue 是一套用于构建用户界面的渐进式框架。
</p>

好,现在我们点击一下按钮,可以看到答案就显示出来了,再点一下,答案就隐藏了。不过,这里有一个小问题,就是按钮的文案没有发生变化,在显示了答案之后,按钮的文案还是显示答案,这时应该改为隐藏答案。那么我们也可以在模板插值中,根据 showAnswer 属性的值,来显示不同的文本,因为模板插值中我们可以直接使用 JavaScript 表达式,所以这里我们可以使用三目运算符来控制按钮的文案。这里变化的文案是『显示』和『隐藏』两个字,而『答案』这两个字不变,所以我们可以这样写 {{ showAnswer ? "隐藏" : "显示" }}答案

<button @click="showAnswer = !showAnswer">
{{ showAnswer ? "隐藏" : "显示" }}答案
</button>

这样,vue 就会根据 showAnswer 属性的值,来改变按钮的文案了,点击一下,在显示答案的时候,按钮变成了隐藏答案,而答案隐藏时,按钮就又变成了显示答案。

小结

这个就是在 vue 中注册和处理事件的方法,使用 v-on: 或 @ 简写形式,加上去掉 on 的 html 事件名来注册事件,之后在指令的值中,使用 JavaScript 表达式来处理事件。另外也见识到了 vue 响应性的魅力,当处理事件时,改变了 data 中的某个属性值,那么所有使用到这个属性值的地方都会进行更新。

提示

《Vue 3.x 全家桶完全指南与实战》课程已上线,包括 Vue 3.x、TypeScript、Vue Router 4.x、Vuex 4.x 所有初级到高级的语法特性详解,让你完全胜任 Vue 前端开发的工作。点击查看详情。

《React即时通信UI实战》课程,利用 Storybook、Styled-components、React-Spring 打造属于自己的组件库。

新书《JavaScript 基础语法详解》已上架,可在京东、当当、淘宝等各大电商购买