没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式

迄今为止,我们比较深入了讲了 “绑定” 和 “渲染” 相关的内容。

而且,通过上一篇 “条件渲染”,我们还能实现某种程度动态的画面切换。

你可能也注意到了 —— 尤其是如果你有 GUI 应用程序的开发经验的话 —— 

我们在 “条件渲染” 这一篇里,并没有处理 “单选按钮” 的 “选中状态变更” 事件,

而是使用了基于 “绑定” 的数据驱动画面 (MVx)的方式,由 Vue 帮我们完成了事件处理和画面刷新的工作。

你也能感觉到这种做法的局限 —— 比如说没法处理 按钮 的点击事件 —— 所以,接下来让我们学习一下普通事件是怎么处理的。

Vue 官网上相关的内容在:https://cn.vuejs.org/v2/guide/events.html,不过我们还是掰碎了、挑最常用的来说。

 

1、HTML 原生的事件处理


由于 Vue 只是帮我们简化了 HTML 的相关处理,所以我们还是从 HTML 的原生事件处理入手;知道了本质,举一反三更加容易。

假设我们要做一个按钮,点击后提示 “Hello, World!”。为了顺带了解一下事件参数,我们在提示信息里把点击时鼠标的位置也显示出来。

没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第1张图片

使用原生的 HTML ,有以下 2 种实现方式。

1)在 元素上直接使用 onclick 属性设置回调函数: (注意 onclick 属性的值设置成了一个字符串)

    
    

如果你对 JavaScript 的函数不太熟,可以顺带看一下 https://zh.javascript.info/function-basics。

2)使用 JavaScript 动态设置 元素上的 onclick 属性: (注意 onclick 属性的值设置成了一个函数,同时需要给按钮加上 id 或者其他标识)

    
    

原生 HTML 中有各式各样的事件(不过对比 WIN32 的 MSG 类型定义也只是小巫见大巫了),

可以看  https://zh.javascript.info/introduction-browser-events  有个大概的印象,

遇到具体的事件再查询 https://zh.javascript.info/event-details 和 https://zh.javascript.info/forms-controls,(略去了页面声明周期、文档加载和观察者等不常用的部分)

没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第2张图片

比如说 onclick 事件的详细描述在 https://zh.javascript.info/mouse-events-basics。

(当然,英文无障碍的话首选 MDN https://developer.mozilla.org/zh-CN/docs/Web/API/Element)

 

2、Vue 中的事件处理方法


我们再来看一下,用 Vue 怎么实现同样的效果。

    

 

仔细比对一下原生 HTML 的写法,可以发现 Vue 的写法有几个特征,可以快速复制:

1)使用 v-on:click 属性代替了原生的 onclick 属性 —— 但是仍然可以监控到 点击 事件。

2)用 $event 代替了原生的 event —— 用于传递事件的参数。

     没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第3张图片  

3)在 methods 中间增加了 v-on:click 中指定的函数

    没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第4张图片

最基本的事件处理方式,就是这样的 —— 简单吧?

Vue 还允许把 v-on 简写成 @ ,于是还能再少敲 4 个字符。(还记得 : 是什么的简写不?千万不要记混了 ......)

没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第5张图片

 

3、Vue 事件处理中的参数传递


1)传递原生 DOM 事件的参数:

上面的例子中,我们使用 Vue 自定义的 $event 来传递原生 DOM 事件的参数。

如果只使用原生 DOM 事件的参数的话,咱们可以进一步简化,只在 @click 属性中设置函数的名称 —— 连 $event 都不用写。

没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第6张图片

但是,一定要注意,只写函数名,连 () 都不要写。不然意思就变成了,事件处理函数中不使用任何参数 —— 点击按钮的时候,处理函数也会报错。

没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第7张图片

2)不使用参数:

以按钮点击事件为例,不同的按钮可能本身就代表着不同的业务逻辑,对应的处理函数也不一样;这时,可能连参数都不用,通过处理函数就能直接区分出来。

比如说,我们写这篇文章的编辑画面,右上角有 “保存草稿”  和  “发布文章”  这两个按钮。

它们的业务处理不一样,代码中可能就直接绑定了不同的处理函数。

没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第8张图片

3)使用自定义参数:

同样是按钮,也有业务逻辑基本一样的情况。

比如说,在表格中展示一组查询结果,并且在每一行中加入对应的操作按钮,点击后可以编辑这一行对应的记录。

没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第9张图片

此时,我们需要给把所有的 “编辑” 按钮的点击事件绑定到同一个函数,但是调用时把本行对应的数据传过去。

核心代码大概是这样的:

1)使用 v-for 来批量生成每一行;

2)每一行的 “编辑” 按钮的点击事件都绑定到同一个 edit 函数,而且在调用时指定本行(也就是 v-for 中 in 之前迭代的部分)的数据。

        
          {{student.id}}
          {{student.name}}
          
        
        methods: {
          edit: function(id) {
            alert("编辑学生信息,id = " + id);
          }
        }

类似的还有 单选框、复选框、选择框 中的选中状态发生变化时的处理函数,也会采用类似的方式批量生成和设置处理函数。

(要是有点儿忘了,可以翻翻:没时间学 Vue (5) —— 绑定(四):面向单选、复选和选择框的 v-model。)

 

4、Vue 事件处理中处理绑定数据、调用其他函数


我们已经知道如何绑定(接收)事件了,可是事件的处理函数里要写些什么呢?不能总像上面的例子那样,什么也不做、光弹个提示框。

正常的事件处理里面,我们总是要处理一些画面上的数据、给后台发个请求然后把后台的返回结果展示出来的。

也就是说,事件处理函数里面经常要处理(获取 and/or 更新)绑定数据的,而且可能会调用其他的处理函数。

比如说,我们要做一个简单的调整某个数值的功能,画面大概是这样的: 

默认值是 10,按 - 号按钮就减一,按 + 号按钮就加一。

一种实现方式可能是这样的:(从简单描述的角度,先不合并这两个按钮的事件处理函数)

    
{{value}}

其中,需要特别注意的是,我们在函数里操作绑定数据的时候,前面要加一个 this 的


如果不加的话,画面上的数值就不会变了 —— 也就是根本没有操作到绑定数据。

这点跟很多熟知的编程语言不太一样 —— 比如说 C++、Java 和 C# 里,访问成员变量的时候,加不加 this 都是没问题的。

之所以这么另类,主要是因为 JavaScript 固有的 this 会随着上下文变化的历史遗留问题。

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this

https://www.ruanyifeng.com/blog/2018/06/javascript-this.html

此外,Vue 对于 data 和 methods 的封装,也稍微让问题更复杂了一点儿。

简单来说,你可以这么理解 Vue 处理 data 和 methods 的方式 (把 data 和 methods 抽出来,合并到另一个新的对象中去了)

没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第10张图片

所以,从 methods 中访问 data 的时候,必须加上 this,不然就找不到了。

我们也可以进一步推测,methods 中的函数相互调用的时候(比如在 minusOne 中调用 plusOne 的话),也是需要加 this 的。

你可能会好奇地问,要是我要在函数中访问 el 的话,是不是也是加 this 就行了呢?

没时间学 Vue (8) —— 事件处理(一):简单 DOM 事件的处理方式_第11张图片

恭喜你又问了一个超越 80% 同行的问题,Vue 并没有把 el 简单地添加到新的对象里,所以加了 this 也访问不到。

非要打破砂锅问到底的话,答案在这里: https://cn.vuejs.org/v2/api/#el 。

 

5、常见 DOM 事件


除了上面提到的 点击 事件,常见的 DOM 事件还有:

1)鼠标拖拽事件:

    https://zh.javascript.info/mouse-drag-and-drop

2)键盘事件:(KeyDown、KeyUp )

    https://zh.javascript.info/keyboard-events

接下来是各种混乱的 输入类 组件,根据类型不同,触发的事件也不同。

3)关于各类文本框(