vue2之事件

159 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

事件不管是在原生还是vue中都是经常会用到的,所以了解事件就是一件非常有必要的事情,我们这篇文章主要是围绕vue来介绍一下事件是如何使用的,以及我们常用的一些事件机制。

事件处理

1. 监听

在vue中事件监听是通过v-on指令去监听的,并在触发的时候运行一些JavaScript代码。即v-on:后面加事件类型

<span class="btn" v-on:click="clearFun">点我触发点击事件</span>

v-on指令也可以简写成@符

<span class="btn" @click="clearFun">点我触发点击事件</span>

2. 事件处理方法

2.1 基础用法

在使用事件处理的时候我们需要使用v-on去监听事件,我们可以直接将事件的内容写在v-on指令后面,比如下面这种:

<span class="btn" v-on:click="num++">{{num}}</span>

对于比较复杂的事件内容,我们通常会写一个方法,将逻辑写在方法里面,然后将方法名绑定在v-on指令上。

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

methods: {
  sayHello () {
    alert('hello world!')
  } 
}
2.2 传参用法

上面介绍的都是一些很基础的用法,但是在实际开发中,我们通常需要传参,下面介绍一下传参的用法。不传参的时候,我们可以直接在v-on后面绑定方法名,但是如果需要传参的话我们需要使用括号,里面传参

<button @click="showMsg('hello')">showMsg</button>

methods: {
  showMsg (msg) {
    alert(msg)
  } 
}

这样我们传什么参数就会弹出什么信息 image.png

2.3 事件对象用法

在事件中我们有一个很重要的事件对象event,只要有了事件就一定会存在事件对象,事件对象是系统自动创建的,里面包含了很多属性。 在Vue中需要在v-on绑定的方法中传一个$event,这样就能拿到事件对象了

<button @click="showMsg($event)">showMsg</button>
methods: {
  showMsg (e) {
    console.log(e)
  }
}

需要注意的是如果想要使用事件对象,必须传入$event,否则会报错。 image.png

从打印信息可以看出,事件对象里面包含很多信息,我们常用的就是以下几个属性,重点关注一下就行。

1). type属性

事件类型

2). target和currentTarget

target是触发事件的对象,currentTarget是绑定事件的对象

3). keyCode

被按下键盘的键码(ASCII码),这个只有在键盘事件中才会有对应的属性

4). ctrlKey, altKey, shiftKey

这几个属性值也都是在键盘事件中才会有对应的属性。ctrlKey返回是否按下了ctrl键,altKey返回是否按下了alt键,shiftKey返回是否按下了shift键

5). screenX与screenY

screenX是鼠标点击的坐标距电脑屏幕水平方向的距离,screenY鼠标点击的坐标距离电脑屏幕垂直方向的距离

6). offsetX与offsetY

offsetX鼠标点击的坐标距自身水平方向元素的距离,不受滚动条影响。offsetY鼠标点击的坐标距自身垂直方向元素的距离

7). clientX与clientY

clientX是鼠标点击的坐标距窗口可视区水平方向元素的距离,clientY是鼠标点击的坐标距窗口可视区垂直方向元素的距离

2.4 事件类型

对于我们开发vue项目来说,常见的事件方法主要有下面这几种js原生事件和自定义事件

2.4.1 鼠标点击事件 点击事件是在开发中用的最多的事件,有单击是双击事件两种

  • click: 单机事件
  • dbclick:双击事件

2.4.2 焦点事件 焦点事件有两种,失去焦点和获得焦点,这种事件一般用于input输入框中

  • focus: 元素获得焦点(不会冒泡)
  • blur: 元素失去焦点(不会冒泡)

2.4.3 鼠标其他事件 除了上面介绍的鼠标点击事件外,鼠标还具有其他的一些事件。

  • mousedown: 在元素上按下任意鼠标按钮
  • mouseup: 在元素上释放任意鼠标按键
  • mouseenter: 指针移到有事件监听的元素内
  • mouseleave: 指针移出元素范围内(不会冒泡)
  • mousemove: 指针在元素内移动时持续触发
  • mouseover: 指针移到有事件监听的元素或者它的子元素内
  • moseout: 指针移出元素,或者移到它的子元素上
  • select: 有文本被选中
  • wheel: 滚轮向任意方向移动

2.4.4 表单事件 表单事件一般是用在form元素上的,常见的有两种元素

  • reset: 点击重置按钮时触发
  • submit:点击提交按钮时

2.4.5 $emit自定义事件 除了上面这些原生的js事件外,vue还可自定义事件,这种情况一般用于父子组件之间传值时:

子组件child.vue

goToParent() {
  this.$emit('childToParent')
}

父组件parent.vue

<child @childToParent="getChildData" />

getChildData() {
  // 这里可以拿到子组件给父组件传递的值
}

3. 修饰符

在vue中,修饰符分为以下五种:

  • 表单修饰符
  • 事件修饰符
  • 鼠标按键修饰符
  • 键值修饰符
  • v-bind修饰符

3.1 表单修饰符

3.1.1 lazy

在表单元素中,只有当光标离开标签的时候,才会将值赋给value。

<input type="text" v-model.lazy="msg" >

3.1.2 trim

这个修饰符会自动过滤输入的首空格和尾空格,中间的不会过滤

<input type="text" v-model.trim="msg" >

3.1.3 number

这个修饰符能将输入的内容自动转成number类型。

<input type="text" v-model.number="msg" >

3.2 事件修饰符

在js事件机制中,我们知道事件分为捕获阶段和冒泡阶段。

捕获阶段就是从根元素往下找到目标元素的过程。 冒泡阶段就是从目标元素往上到根元素的过程。 image.png

为了避免事件冒泡,默认行为等,vue增加了一些事件修饰符

3.2.1 stop

这个修饰符阻止了事件冒泡,相当于原生事件的event.stopPropagation方法

下面这个例子是存在事件冒泡的事件

<template>
  <div class="test-wrapper">
    <div class="box1" @click="click1">
      <div class="box2" @click="click2">
        <div class="box3" @click="click3"></div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data () {
    return {
    }
  },
  methods: {
    click1 () {
      console.log('!!!box1 click')
    },
    click2 () {
      console.log('!!!box2 click')
    },
    click3 () {
      console.log('!!!box3 click')
    }
  }
}
</script>
<style lang="scss" scoped>
  .test-wrapper {
    .box1 {
      width: 300px;
      height: 300px;
      border: 1px solid #999;
      .box2 {
        width: 200px;
        height: 200px;
        border: 1px solid #999;
        .box3 {
          width: 100px;
          height: 100px;
          border: 1px solid #999;
        }
      }
    }
  }
</style>

1669471171287.png

使用.stop

<div class="box1" @click="click1">
  <div class="box2" @click="click2">
    <div class="box3" @click.stop="click3"></div>
  </div>
</div>

image.png

3.2.2 prevent

这个修饰符会阻止元素默认行为。比如下面的a标签的点击事件会触发跳转

<a href="https://juejin.cn/" @click="console.log('触发事件了')">点我跳转</a>

效果: 打印完休息后,页面会跳转到掘金首页

使用.pevent之后就不会跳转

<a href="https://juejin.cn/" @click.prevent="console.log('触发事件了')">点我跳转</a>
3.2.3 self

这个修饰符是只有当event.target是当前元素自身时触发处理函数

<div class="box1" @click="click1">
  <div class="box2" @click="click2">
    <div class="box3" @click.self="click3"></div>
  </div>
</div>

image.png

3.2.4 once

这个修饰符说明事件只能触发一次,后面的都不会触发

<div class="box3" @click.once="click3"></div>
3.2.5 capture

前面介绍的这几种修饰符是比较常见的,下面介绍的几种修饰符用的相对来说没有那么多 一般事件的触发都是在冒泡阶段来触发的,像上面那个例子一样,如果想要事件触发从包含这个元素的顶层开始往下触发

<div class="box1" @click="click1">
  <div class="box2" @click.capture="click2">
    <div class="box3" @click="click3"></div>
  </div>
</div>

1669472534597.png

3.2.6 passive

当我们需要监听元素滚动的时候,会一直触发onscroll事件,导致页面卡顿,这时就可以使用这个修饰符来避免这种卡顿

<div class="box3" @scroll="onScroll"></div>
3.2.7 native

这个修饰符能让组件像html内置标签那样监听组件根元素的原生事件,否则需要借助自定义事件来完成。不过需要注意的是这个native修饰符只能用来修饰组件元素

<child class="box3" @click.native="myClick"></child>

3.3 鼠标按键修饰符

3.3.1 left

这个修饰符表示按了鼠标左键才会触发

<div class="box3" @click.left="consoleMsg('left')"></div>
3.3.2 right

这个修饰符表示按了鼠标左键才会触发

<div class="box3" @click.right="consoleMsg('right')"></div>
3.3.3 middle

这个修饰符表示按了鼠标左键才会触发

<div class="box3" @click.middle="consoleMsg('middle')"></div>

3.4 键盘修饰符

键盘修饰符是用来修饰键盘事件的,只有按键为keyCode的时候才会触发,其中keyCode可以为以下两种类型的值

  • 普通键值:enter, tab, delete, space, esc, up等
  • 系统修饰键:ctrl, alt, meta, shift
<div class="box3" @keyup.keyCode="consoleMsg('ok')"></div>

3.5 v-bind修饰符

这类修饰符主要是为属性进行操作,通常有三种:

  • async
  • prop
  • camel
3.5.1 async

这个修饰符能对props进行一个双向绑定

// 父组件
<parent :message="msg" @update:myMessage='update'></parent>
update(e) {
  this.msg = e
}

// 子组件
send() {
  this.$emit('update:myMessage', params);
}

可以使用async

// 父组件
<child :message.async="bar"></child>

// 子组件
this.$emit('update:myMessage', params);
3.5.2 prop

这个修饰符设置自定义标签属性,避免暴露数据

<input :type="text" v-model="msg" :index.prop="index"/>
3.5.3 camel

这个修饰符可以将变量命名为驼峰命名法

<input :type.camel="text" v-model="msg" />