正文
在本文我就不详细介绍Vue.js是如何给组件绑定事件了的,大家都知道是通过v-on:事件="事件名"
或者它的语法糖 @事件="事件名"
。
Vue.js为我们提供了很多不同种类的修饰符,例如事件修饰符
、按键修饰符
、鼠标按键修饰符
,我们就对这三种修饰符进行详细的介绍。
一、事件修饰符
首先,来看一下Vue.js为我们提供的事件修饰符有哪些吧。
修饰符名称 | 作用 |
.stop | 阻止事件进行传递 |
.prevent | 阻止事件的默认行为 |
.capture | 使该事件最先触发 |
.self | 限制事件是由自身触发才进行处理,即事件冒泡触发该事件无效 |
.once | 规定该事件只会触发一次 |
.passive | 会立即触发事件的默认行为,即不会被event.preventDefault()影响 |
.stop
未使用修饰符 .stop
的情况:
<template> <div class='father' @click='btnClick1'> <div class='child' @click='btnClick2'> <div class='grandson' @click='btnClick3'></div> </div> </div> </template> <script> ... btnClick1() { console.log('div1被点击') }, btnClick2() { console.log('div2被点击') }, btnClick3() { console.log('div3被点击') } ... </script>
当我们点击类名为grandson的div标签时,会打印以下内容
div1被点击 div2被点击 div3被点击
我们再来看一下使用了修饰符 .stop
是什么样子的:
<template> <div class='father' @click='btnClick1'> <div class='child' @click.stop='btnClick2'> <div class='grandson' @click='btnClick3'></div> </div> </div> </template> <script> ... btnClick1() { console.log('div1被点击') }, btnClick2() { console.log('div2被点击') }, btnClick3() { console.log('div3被点击') } ... </script>
这时我们进行同样的操作,打印结果如下:
div1被点击 div2被点击
类名为father的div标签上的click事件并没有被触发,其实是因为修饰符.stop
相当于 stopPropagation()
的作用,阻止了事件继续向上传递
.prevent
该修饰符就不多做掩饰了,相当于 preventDefault()
的作用
.capture
该修饰符是将事件触发顺序提前,来继续看上面那个例子,我们用了该修饰符后,是怎么样一个情况
<template> <div class='father' @click.capture='btnClick1'> <div class='child' @click='btnClick2'> <div class='grandson' @click='btnClick3'></div> </div> </div> </template> <script> ... btnClick1() { console.log('div1被点击') }, btnClick2() { console.log('div2被点击') }, btnClick3() { console.log('div3被点击') } ... </script>
我们点击最中间的元素,看看结果如何:
div1被点击 div3被点击 div2被点击
我们可以看到,最外层的div使用了修饰符 .capture
,所以当我们点击最里面的div时,本应该由内向外依次触发事件,但此时却先触发了最外层的div的事件,然后再按原本的顺序依次触发
.self
该修饰符根据字面意思也很好理解,就是只有当自身触发该事件才会调用处理的函数,我们来接着上面的例子来看
<template> <div class='father' @click='btnClick1'> <div class='child' @click.self='btnClick2'> <div class='grandson' @click='btnClick3'></div> </div> </div> </template> <script> ... btnClick1() { console.log('div1被点击') }, btnClick2() { console.log('div2被点击') }, btnClick3() { console.log('div3被点击') } ... </script>
我们先来点击类名为grandson的div,结果如下
div3被点击 div1被点击
我们再来点击一下类名为child的div,结果如下
div2被点击 div1被点击
我们可以看到,当点击了最里面的div时,事件冒泡到中间的div,但因为使用了修饰符 .self
,所以它并没有调用事件的处理函数
.once
该修饰符表示事件只能被触发一次,我们来看例子
<template> <div class='father' @click='btnClick1'> <div class='child' @click='btnClick2'> <div class='grandson' @click.once='btnClick3'></div> </div> </div> </template> <script> ... btnClick1() { console.log('div1被点击') }, btnClick2() { console.log('div2被点击') }, btnClick3() { console.log('div3被点击') } ... </script>
我们来对类名为grandson的div进行第一次点击,结果如下
div3被点击 div2被点击 div1被点击
那我们对它进行第二次点击,结果如下
div2被点击 div1被点击
我们可以看到,因为最内部的div使用了修饰符 .once
,所以只有在第一次点击它的时候,它才会调用事件处理函数,之后再点击,就不会触发了
.passive
这个修饰符也就不多做演示了,作用呢,就是使事件立即触发默认行为。比如我们给一个表单提交事件 submit
设置了event.preventDefault()
,阻止了表单提交的默认行为,但我们对该事件使用了修饰符 .passive
,点击提交表单的时候,event.preventDefault()
就会失效,即仍然进行表单提交的默认行为。
==注意==:但这里一定要注意,修饰符.prevent
和修饰符 .passive
不能一起使用,系统会忽略前者。接下来我们会介绍到修饰符的组合使用。
修饰符的组合使用
修饰符是可以组合使用的,类似这样的.stop.once
。我们来看看修饰符.stop
和修饰符.once
一起使用会有什么效果
<template> <div class='father' @click='btnClick1'> <div class='child' @click.stop.once='btnClick2'> <div class='grandson' @click='btnClick3'></div> </div> </div> </template> <script> ... btnClick1() { console.log('div1被点击') }, btnClick2() { console.log('div2被点击') }, btnClick3() { console.log('div3被点击') } ... </script>
我们来点击类名为grandson的div,结果如下
div3被点击 div2被点击
这里,因为div2使用了修饰符 .stop
,所以点击事件没有向上继续传递。然后我们再来点击一下,看看结果如何
div3被点击 div1被点击
因为div2使用了修饰符 .once
,所以第二次点击以及接下来的点击都不会触发它的事件处理函数了。
二、按键修饰符
我们可以对 keyup
或 keydown
等键盘按键的事件进行修饰符的使用。Vue.js给我们提供了一些常用按键的修饰符,我们来看一下
.enter //回车键 .tab //tab键 .delete //delete键和退格键 .esc //esc键 .space //空格键 .up //↑键 .down //↓键 .left //←键 .right //→键
我们只需要在事件的后面跟上一个按键修饰符就可以规定按哪个键才会触发事件了。
键盘上那么多键,我们如果要规定按别的键怎么办?其实我们只需要自己对别的键进行配置一下就可以了,例如
Vue.config.keyCodes.f1 = 112
这样给全局配置完以后,我们就可以使用按键修饰符 .f1
了
<div @keyup.f1="divClick"></div>
三、系统修饰键
我们在平时见过这样一个需求,按住ctrl + f1,就可以触发某些操作,所以Vue.js还提供了一些修饰键来帮助我们完成这样的需求。
.ctrl .alt .shift .meta //该修饰键是作用于Mac系统的电脑的 .exact
修饰键可以配合事件使用,例如@click.ctrl='btnClick'
表示要按住 ctrl
去点击才会触发事件;同时修饰键还能跟按键修饰符一起使用,例如 @keyup.alt.enter='keyUp'
表示按住alt
的同时按住回车键才会触发该事件。
但其实使用时我们会发现这样一个情况,@keyup.alt.enter='keyUp'
,我们按住 alt
,再按住一个空格键或者tab
键,然后按住回车键,也可以触发该事件。所以Vue.js新增了一个修饰符.exact
,用来完成按键的精确触发。
@keyup.alt.enter.exact='keyUp'
,这样使用了修饰符.exact
以后,我们必须只有在按住alt
和回车键时,才能触发该事件了,再多按了一个键都不能触发。
四、鼠标按钮修饰符
当然了,鼠标上还有三个键呢,即左键 、右键 、滚轮键,他们也有对应的修饰符,分别是 .left
、.right
、.middle
,这里也就不做多余的演示了。
五、其它修饰符
除了以上提到的修饰符,还有一些其它修饰符用于特定的情况,我们来了解一下
.sync
要了解该修饰符的作用,我们先来回顾一下父子组件之间通信的一个例子
- 子组件情况
展示父组件传递过来的变量title
,并在点击时,向父组件发送一个名为changeValue
的事件,同时也传递过去了一个值。
//我们创建了个名为child-cpn的组件 <div @click='divClick'>{{title}}</div> …… props: ['title'], methods: { divClick() { this.$emit('changeValue', '我是改变后的值') } }
- 父组件情况
父组件将自己的变量origin_title
传递给子组件,同时接收子组件传递过来的事件changeValue
事件以及数据。
//父组件使用了子组件child-cpn <child-cpn :title='{{origin_title}}' @changeValue='changeValue'/> …… data() { return { origin_title: '我是原始值' } }, methods: { changeValue(info) { this.origin_title = info } }
我们都知道父组件传递给子组件的数据是单向变化的,即只有当父组件的数据改变,子组件获得的数据才会跟着改变。所以这个例子中,子组件想改变这个值,通过子组件向父组件通信的方式,告诉父组件,你快把这个值给改一下,修改后的值我也发给你了。就这样,父组件还需要监听子组件传递过来的事件,再用一个方法去处理该事件,就显得很麻烦。
通过了解上面这个例子的需求,我们来引入我们的修饰符.sync
,看看使用了这个修饰符,代码会变得多简洁
- 子组件情况
子组件在向父组件通信时,传递的事件名需要改为这样的格式:update:需要改变的变量名
//我们创建了个名为child-cpn的组件 <div @click='divClick'>{{title}}</div> …… props: ['title'], methods: { divClick() { this.$emit('update:title', '我是改变后的值') } }
- 父组件情况
父组件只需要在传递给子组件变量时,在变量名后面加一个修饰符.sync
,这样的话父组件中的origin_title
就会直接改变成子组件传递过来的参数了。
//父组件使用了子组件child-cpn <child-cpn :title.sync='{{origin_title}}'/> …… data() { return { origin_title: '我是原始值' } }
细心的小伙伴一定发现了,父组件在使用了修饰符.sync
后,省去了@changeValue='changeValue'
和 changeValue(info) {this.origin_title = info}
这两部分代码,变得十分的简洁。
注意:
- 这里我还是要强调一遍哦,子组件在向父组件通信的时候,传递的事件参数必须是
unpdate:需要改变的变量名
这样的格式,这是规定好的。
- 在我们使用了修饰符
.sync
后,传递给子组件数据时,不能使用表达式的形式,例如这样:title.sync="origin_title + '哈哈' "
,这样是会报错的。
.native
该修饰符的作用比较简单,我就几句话描述一下吧
//父组件使用了一个名为child-cpn的子组件,并监听他的click事件,结果是没作用的 <child-cpn @click='cpnClick'/>
有经验的人会知道,在组件的根元素上绑定原始的事件,是没有作用的,不信你们可以自己动手试一下。
但只要我们在该事件后面使用修饰符 .natvie
就可以绑定上原始的事件了
//父组件使用了一个名为child-cpn的子组件,并监听他的click事件,成功绑定 <child-cpn @click.native='cpnClick'/>