目录

1 事件处理

1.1 最简单的事件绑定例子

1.2 默认参数event

1.3 其它自定义参数

1.4 this

2 事件修饰符

2.1 prevent阻止默认事件(常用)

2.2 stop阻止事件冒泡(常用)

2.3 once事件只触发一次(常用)

2.4 capture使用事件的捕获模式

2.5 self只有event.target是当前的操作元素时才出发事件

2.6 passive事件的默认行为立即执行,无需等待事件回调执行完毕

2.7 事件修饰符的连续使用

3 键盘事件

3.1 Vue中常用的按键别名

3.2 最简单的绑定键盘事件的方法

3.3 按下目标键才触发的键盘事件

3.4 tab按键(特殊)

3.5 系统修饰键(特殊)

3.6 自定义按键别名


1 事件处理

1.1 最简单的事件绑定例子

在vue当中,要给元素绑定事件需要用到vue指令,指令一般以v-开头,例如绑定单击事件的指令是v-on:click = “函数名”,简写为@click = “函数名”

例如以下例子:单击button按钮,执行showInfo函数,弹出alert窗口。

<body>
  <button class="btn" v-on:click = "showInfo">点击弹出{{name}}窗口</button>
  <script type="text/javascript">
     Vue.config.productionTip = false;
     const vm = new Vue({
      data:{
        name:"alert"
      },
      methods:{
        showInfo(){
          alert('hello!');
        }
      }
     })
     vm.$mount('.btn')
  </script>
</body>

以上是最简单的事件绑定例子,鼠标悬停、鼠标移出等事件可以参照以上例子。

vm.$mount(".btn")指定了可供vue操作的元素,与el关键字的作用类似,但比el更加灵活。

methods记录了所有的方法,凡事与vue所操作元素有关的方法都应该写在method里面,否则无效。

在button属性里面,使用v-on:click绑定了一个单击事件,当点击此对象时,就执行showInfo函数。

1.2 默认参数event

这一步是探究methods配置项中,函数的传参问题。在上一个例子当中,设置了showInfo函数,这是自定义的函数,现在探究这个函数它默认情况下怎么接收函数。首先,为showInfo设置三个参数的位置,分别为a,b,c,然后后台输出a,b,c这三个参数,看看哪一个参数里面存的有东西。代码如下所示:

<body>
  <button class="btn" v-on:click = "showInfo">点击弹出{{name}}窗口</button>
  <script type="text/javascript">
     Vue.config.productionTip = false;
     const vm = new Vue({
      data:{
        name:"alert"
      },
      methods:{
        showInfo(a,b,c){
          alert('hello!');
          console.log(a,b,c);
        }
      }
     })
     vm.$mount('.btn')
  </script>
</body>

 可以发现输出的a,b,c当中只有a有东西,其他的全部为undefined。可以发现a里面存放的是一个名为PointerEvent(百度翻译:指针事件)的对象,其实就是事件对象event,有点像事件委托当中的event。可以尝试以下代码。

methods:{
  showInfo(event){
    alert('hello!');
    console.log(event.target);
    console.log(event.target.innerHTML);
  }
}

输出结果:分别弹出被点击的标签、被点击标签的文本内容。

1.3 其它自定义参数

先写好两个按钮,这两个按钮点击之后会触发相应的函数,btn1触发showInfo1函数,btn2触发showInfo2函数,showInfo1不传参数,showInfo2传入一个参数。接着,在methods中配置好showInfo1与showInfo2函数。代码如下所示:

<body>
  <button class="btn" v-on:click = "showInfo1">按钮1</button>
  <button class="btn" v-on:click = "showInfo2(66)">按钮2</button>
  <script type="text/javascript">
     Vue.config.productionTip = false;
     const vm = new Vue({
      methods:{
        showInfo1(a){
          console.log( `showInfo1:${a}`);
        },
        showInfo2(a){
          console.log( `showInfo2:${a}`);
        }
      }
     })
     vm.$mount('.btn')
  </script>
</body>

输出结果:

showInfo1没有传入任何参数,所以showInfo1的第一次参数位默认为event ,showInfo2我们给它传入了数字66作为第一个参数,所以showInfo2输出66 ,但这样做之后,event消失了。解决办法,再传入一个$event参数,$event是一个关键字,vue会自动将其解析为event,这个参数无论作为第几个参数都可以。代码如下所示:

<body>
  <div class="btns">
    <button v-on:click = "showInfo1">按钮1</button>
    <button v-on:click = "showInfo2(66,$event)">按钮2</button>//添加$evetn
  </div>
  <script type="text/javascript">
     Vue.config.productionTip = false;
     const vm = new Vue({
      methods:{
        showInfo1(a){
          console.log( `showInfo1:${a}`);
        },
        showInfo2(a,b){//增加形参b
          console.log( `showInfo2:${a},${b}`);
        }
      }
     })
     vm.$mount('.btns')
  </script>

输出结果:

 1.4 this

methods中的配置函数,都是被vue所管理的函数,this指向vm或组件实例对象,所以showInfo中的this指向vue实例(即例子当中的vm),若showInfo使用箭头函数,则this指向window。箭头函数的写法如下所示:

 methods:{
        showInfo:(event) => {
          alert('hello!');
          console.log(event.target);
          console.log(event.target.innerHTML);
        }
      }

受vue所管理的函数最好写成普通函数,而不是写成箭头函数,不然会影响this的指向。

2 事件修饰符

2.1 prevent阻止默认事件(常用)

一般用在有默认事件的标签上,例如点击a标签时的默认跳转行为,写法是@click.prevent="函数名"

2.2 stop阻止事件冒泡(常用)

例如在以下代码当中,若先将button元素中的v-on:click.stop="showInfo1"改写为v-on:click="showInfo1",那么此时点击button按钮会弹出两次alert窗口。为什么?因为button元素和它的父级元素都有click事件,所以,如果点击button按钮不仅会触发button的单击事件,同时也会触发div的click事件,这种行为叫做冒泡,若在button元素中的单击事件中添加stop事件修饰符,那么会在button元素这一步停止冒泡行为。

<body>
  <div v-on:click="showInfo1" class="btns">
    <button v-on:click.stop="showInfo1">按钮1</button>
  </div>
  <script type="text/javascript">
    const vm = new Vue({
      methods: {
        showInfo1() {
          alert(`弹出信息!`);
        }
      }
    })
    vm.$mount('.btns')
  </script>
</body>

2.3 once事件只触发一次(常用)

以上面的代码为例,每一次点击button都会出现alert弹窗,如果我想让它在第一次点击的时候出现弹窗,以后无论点多少从都不出现弹窗,该怎么做。

只需将button的单击事件改写为v-on:click.once='showInfo1'即可。

2.4 capture使用事件的捕获模式

捕获(由外往内),冒泡(由内往外),先捕获再冒泡,程序默认在冒泡阶段处理事件。

capture可以使程序在捕获阶段就开始处理事件。

首先观察以下不加任何修饰符的代码。

<body>
  <div v-on:click="showInfo1(1)" class="btns">
    div1
    <div v-on:click="showInfo1(2)">
      div2
    </div>
  </div>
  <script type="text/javascript">
    const vm = new Vue({
      methods: {
        showInfo1(number) {
         console.log(`${number}`);
        }
      }
    })
    vm.$mount('.btns')
  </script>
</body>

代码的大致意思是:我点击哪一个div元素就在控制台输出它的序号,观察它的输出顺序。若点击div1,则后台只输出1,若点击div2,则后台就接着输出2、1(有先后顺序),为什么点击div2的时候还要多输出1呢?因为默认使用了事件的冒泡模式,事件处理函数默认在冒泡阶段被执行。现在我想让div1在捕获阶段就被执行,那么只需要在div的单击事件上添加capture事件修饰符即可。代码示例如下:

<body>
  <div v-on:click.capture="showInfo1(1)" class="btns">
    div1
    <div v-on:click="showInfo1(2)">
      div2
    </div>
  </div>
  <script type="text/javascript">
    const vm = new Vue({
      methods: {
        showInfo1(number) {
         console.log(`${number}`);
        }
      }
    })
    vm.$mount('.btns')
  </script>
</body>

此时若再来点击div2,则控制台弹出1、2(有先后顺序),与刚才的截然相反。

但有一个误区值得注意,div1的事件是在捕获阶段被触发的,div2的事件仍然是在冒泡阶段触发的,简单总结就是有capture的事件才会在捕获阶段触发,没有capture的事件仍然在冒泡阶段被触发,这一点可以通过以下例子被证实:

<body>
  <div v-on:click.capture="showInfo1(1)" class="btns">
    div1
    <div v-on:click="showInfo1(2)">
      div2
      <div v-on:click="showInfo1(3)">
        div3
      </div>
    </div>
  </div>
  <script type="text/javascript">
    const vm = new Vue({
      methods: {
        showInfo1(number) {
         console.log(`${number}`);
        }
      }
    })
    vm.$mount('.btns')
  </script>
</body>

观察代码发现,只有div1有capture,所以当点击div3的时候,控制台先后输出1、3、2。

2.5 self只有event.target是当前的操作元素时才出发事件

这个2.5的标题可能有点难以理解,首先来看看event.target是什么。先来个例子:

<body>
  <div v-on:click="showInfo2" class="btns">
    div
    <span v-on:click="showInfo1">
      span
    </span>
  </div>
  <script type="text/javascript">
    const vm = new Vue({
      methods: {
        showInfo1(event) {
         console.log(`我是span我点击的是${event.target}`);
        },
        showInfo2(event) {
         console.log(`我是div我点击的是${event.target}`);
        }
      }
    })
    vm.$mount('.btns')
  </script>
</body>

以上代码大致意思是,若点击div则执行showInfo1,若点击span则执行showInfo2。

若点击div,则后台输出情况如下:这一条结果对应的是div标签的事件,且从语句中我们可得知被点击的是div标签。

若点击span,则后台输出情况如下:因为冒泡输出了两个结果,但从两条结果中都可获知被点击的是span标签。

 所以,综上所述,event.target代表被点击的对象,无论当前被捕获(或冒泡)到哪一个元素,event.target的值都不变。

再次回到self事件修饰符,只有self的作用对象与event.target目标对象是同一个时,事件才被执行。以下是示例代码:(在第二行添加了self)

<body>
  <div v-on:click.self="showInfo2" class="btns">
    div
    <span v-on:click="showInfo1">
      span
    </span>
  </div>
  <script type="text/javascript">
    Vue.config.productionTip = false;
    const vm = new Vue({
      methods: {
        showInfo1(event) {
         console.log(`我是span我点击的是${event.target}`);
        },
        showInfo2(event) {
         console.log(`我是div我点击的是${event.target}`);
        }
      }
    })
    vm.$mount('.btns')
  </script>
</body>

 这时候点击span就不会出现两条结果了,而是只出现“我是span我点击的是[objectHTMLSpanElement]”。

为什么这时候只有一条语句呢,因为点击span后,代码首先执行span的事件,然后再冒泡到div,发现div有self,但event.target的并不是div,所以div的事件就没有执行。若直接点击div,则div的事件正常执行。

2.6 passive事件的默认行为立即执行,无需等待事件回调执行完毕

事件的默认行为就例如:a标签点击会跳转、鼠标轮滚动页面也会滚动等等。

@scroll是滚动条滚动事件,@wheel是鼠标滚轮滚动事件,两者有区别。

passive一般用在什么情况?(如下)

以鼠标滚动事件为例,当不考虑passive时,并且设置了滚动时需要执行函数的机制时,执行顺序是:

触发滚动事件——执行滚动时的函数——页面滚动

以上顺序需要等待函数执行完毕页面才能滚动,若所执行的函数耗时非常大,就会造成卡顿现象。

面对此现象,如果加上passive事件修饰符,那么函数和默认事件就会同时执行,且不会造成页面卡顿现象。

2.7 事件修饰符的连续使用

如果既需要阻止冒泡,又需要阻止默认跳转行为,则写法应如下:

@click.stop.prevent = "函数名"或者@click.prevent.stop = "函数名",两种写法任选其一,效果一致。

3 键盘事件

3.1 Vue中常用的按键别名

回车 => enter

删除 => delete

退出 => esc

空格 => space

换行 => tab

上 => up

下 => down

左 => left

右 => right

Vue当中未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)

3.2 最简单的绑定键盘事件的方法

键盘事件常用的有两个:keydown(键盘按下时执行)和keyup(键盘按下后弹起时执行)

绑定键盘事件的写法为@keyup="函数名"(v-on:keyup="函数名"),可参照以下代码。

每一个按键都有自己的名字与编码,以下代码执行的是 在按下任意键之后,控制台显示该按键的按键名(key)与按键编码(keyCode)。keyCode在web标准中已经被废弃

<body>
  <div class="btns">
    <input type="text" @keyup="keyEvent">
  </div>
  <script type="text/javascript">
    Vue.config.productionTip = false;
    const vm = new Vue({
      methods: {
        keyEvent(event) {
          console.log(event.key,event.keyCode);
        }
      }
    })
    vm.$mount('.btns')
  </script>
</body>

以下例举几个按键:

注意:这里输出的结果开头大写,并非vue当中所提供的别名,vue提供的别名一般用在形如@keyup.enter=“函数名” 上,后面会有详细描述。

3.3 按下目标键才触发的键盘事件

假如现在有一个input标签,在input标签中输入内容,输入完毕后,只有按回车键才能将输入的内容显示在控制台。有两种实现方法:

第一种:使用if进行原始的按键判断方法

<body>
  <div class="btns">
    <input type="text" @keyup="keyEvent">
  </div>
  <script type="text/javascript">
    Vue.config.productionTip = false;
    const vm = new Vue({
      methods: {
        keyEvent(event) {
          if (event.key == 'Enter') {
            console.log(event.target.value);            
          }
        }
      }
    })
    vm.$mount('.btns')
  </script>
</body>

 第二种:使用vue提供的按键判断(要用到vue提供的别名),只需在@keyup后添加别名即可。

<body>
  <div class="btns">
    <input type="text" @keyup.enter="keyEvent">
  </div>
  <script type="text/javascript">
    Vue.config.productionTip = false;
    const vm = new Vue({
      methods: {
        keyEvent(event) {
          console.log(event.target.value);
        }
      }
    })
    vm.$mount('.btns')
  </script>
</body>

但是有一类按键比较特殊,这类按键由多个单词组成,例如CapsLock(大小写切换),它由Caps与Lock组成,写在@keyup后面就应该这样写:   

 @keyup.caps-lock="函数名"

即:将两个单词拆分开用短横线连接,并且将大写字母变为小写。

另外一个需要注意的点是,部分按键无法进行键盘事件的绑定,例如音量键、亮度键等。

3.4 tab按键(特殊)

tab按键自身就有一个功能,就是把焦点从当前元素身上移到另一个元素身上。tab键在按下但还没有抬起来时就已经被触发,所以@keyup对tab键无效,需要使用@keydown来控制tab键。

3.5 系统修饰键(特殊)

系统修饰键(用法特殊):ctrl、shift、alt、meta(也叫徽标键或win键)。

以上按键需要配合keydowm按键才能正常的触发键盘事件。若配合keyup按键,则需要再按下修饰键的同时再按下其他键,随后释放其他键,事件才被触发。

若规定只能按下ctrl+y才能触发键盘事件,应该怎么写?

答案:@keyup.ctrl.y = "函数名"

3.6 自定义按键别名

例如将回车键的别名由enter改为huiche需要怎么改?

写法如下:

vue.config.keyCodes.huiche = 13;

数字13是回车键的编码。huiche是新的别名。

一般不推荐自定义按键名。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐