Vue核心③(事件处理)

     阅读:47

事件处理

事件的基本使用

我们已经知道在原生js中如何去绑定一个事件,那么在Vue中我们怎么实现事件绑定呢?

我们可以先来看一个最简单的例子:
我们点击一个按钮,出现一个弹窗显示你好CSDN。

<body>
    <button id="root" v-on:click="show">点击我会有神奇的事情发生</button>
</body>
<script>
    Vue.config.productionTip=false
    new Vue({
        el:'#root',
        methods:{
            show(){
                alert('你好CSDN')
            }
        }
    })
</script>

v-代表时Vue的指令,on代表是什么时候,click代表是点击的时候。满足条件则Vue执行回调函数,函数名作为值。函数体写在Vue实例对象的methods属性对象中。

这里我们有几个注意的点:

  • 这个show方法会接受一个事件对象

  • show方法中的this是一个Vue实例。但是如果你使用的是箭头函数,他没有自己的this,就会向外部寻找,最后this就是window

    所有被Vue管理的函数(也就是Vue对象里面的函数)最好都使用普通函数

  • v-on:click也有它的简写形式:@click,所以上面的代码也可以写成:

    <button @click="show">点我有神奇的事情发生</button>

这个回调函数也可以接受参数:

<body>
    <div id="root">
        <button  v-on:click="show1">点击我会有神奇的事情发生</button> <br>
        <button  v-on:click="show2(10)">点击我会有神奇的事情发生</button>
    </div>
    
</body>
<script>
    Vue.config.productionTip=false
    new Vue({
        el:'#root',
        methods:{
            show1(){
                alert('你好CSDN')
            },
            show2(num){
                alert(num)
            }
        }
    })
</script>

在函数名之后加一个括号,传入参数即可。不过也会有一个问题:前面我们提到过Vue在调用回调函数的时候会传入一个事件对象,如果我们现在要使用它怎么办呢?

如果直接多创建一个形参是接收不到这个事件对象的。

我们这里需要用到一个占位符$event

例如:

<body>
    <div id="root">
        <button  v-on:click="show1">点击我会有神奇的事情发生</button> <br>
        <button  v-on:click="show2(10,$event)">点击我会有神奇的事情发生</button>
    </div>
    
</body>
<script>
    Vue.config.productionTip=false
    new Vue({
        el:'#root',
        methods:{
            show1(){
                alert('你好CSDN')
            },
            show2(num,event){
                alert(num)
                console.log(event);
            }
        }
    })
</script>

注意:

  • 这里的show1、show2方法也会出现在Vue的实例对象上。但是这里没有使用代理!
    在这里插入图片描述

  • 不过如果你把这个方法写在data中,方法可以正常回调,同时也会进行代理。(也就是说data里面的数据都会进行代理)当然我们不推荐这样写,会降低Vue的执行效率

最后总结一下:
事件的基本使用:

  1. 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
  2. 事件的回调需要配置在methods对象中,最终会在vm上;
  3. methods中配置的函数,不要用箭头函数!否则this就不是vm了;
  4. methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
  5. @click=“demo” 和 @click=“demo($event)” 效果一致,但后者可以传参;

事件修饰符

我们知道点击a标签会自动跳转到指定网址,如果我们现在不想让他执行这个默认行为,怎么办呢,有两种方法:

①在回调方法中,利用事件对象阻止默认行为:

<body>
    <div id="root">
        <a href="http://www.csdn.net" @click="show">点我显示信息</a>
    </div>
</body>
<script>
    new Vue({
        el:'#root',
        methods:{
            show(e){
                e.preventDefault()
                alert('你好CSDN')
            }
        }
    })
</script>

②使用事件修饰符

<body>
    <div id="root">
        <a href="http://www.csdn.net" @click.prevent="show">点我显示信息</a>
    </div>
</body>
<script>
    new Vue({
        el:'#root',
        methods:{
            show(){
                alert('你好CSDN')
            }
        }
    })
</script>

像这样的事件修饰符还有:

  1. prevent:阻止默认事件(常用);
  2. stop:阻止事件冒泡(常用);
  3. once:事件只触发一次(常用);
  4. capture:使用事件的捕获模式;
  5. self:只有event.target是当前操作的元素时才触发事件;
  6. passive:事件的默认行为立即执行,无需等待事件回调执行完毕;

stop、once、passive在这里不做讲解。

capture:使用事件的捕获形式
我们知道在JS的事件流中分为捕获阶段冒泡阶段,现在我们来看下面的两个嵌套的盒子:
在这里插入图片描述
如果我们给div1和div2均绑定了点击事件。那么在我们点击div2的时候,就会依次出现左边蓝色箭头的捕获阶段和右边红色箭头的冒泡阶段,我们可以知道真正的事件处理在冒泡阶段,最终的结果就是先触发div2的点击事件,再触发div1的点击事件。但是如果我们想在捕获阶段就处理事件呢?这个时候我们就可以使用capture事件修饰符,我们最后的结果变成为先触发div1的点击事件,再触发div2的点击事件。

注意:给谁加,谁的事件就在捕获阶段被处理。上面的那个例子中,我们应该给外面的盒子div1加capture修饰符.

self:只有event.target是当前操作的元素时才触发事件
我们还是提供一个场景:
在这里插入图片描述
在这里插入图片描述
如果我们现在点击按钮,会因为冒泡机制而依次触发button和div的事件。不过注意这两次事件的event.target都是button元素。

在这里插入图片描述
这两次事件触发元素都是button

倘若我们现在给div加一个self修饰符,那么当冒泡到div的时候发现event.target不符合当前div元素,就不会触发事件,从另一个角度说我们可以利用这一点去阻止冒泡。

注意:事件修饰符可以叠加
例如:
@click.prevent.stop="showInfo"表示先阻止默认事件,再停止冒泡。
@click.prevent.stop="showInfo"表示先停止冒泡,再阻止默认行为。
不过最好不要与once叠加,容易出错

键盘事件

现在我们想在按下键盘上的enter键时触发事件。在原生js中我们可能需要去知道enter键的keycode,再利用条件判断来完成。但是现在Vue为我们提供了常用的按键别名是我们可以快速达成目标。

Vue中常用的按键别名:

  • 回车 => enter
  • 删除 => delete (捕获“删除”和“退格”键,也就是Backspace和Delete两个按键)
  • 退出 => esc
  • 空格 => space
  • 换行 => tab (特殊,必须配合keydown去使用)
  • 上 => up
  • 下 => down
  • 左 => left
  • 右 => right

那么我们如何去使用呢?

<div id="root">
	<h2>欢迎来到CSDN学习</h2>
	<input type="text" placeholder="按下回车提示输入" @keydown.enter="showInfo">
</div>

keydown和keyup是两个常用的键盘事件:
keyup是在按键按下回弹时触发
keydown是直接按下触发

如此在我们按下enter键的时候,事件就会被触发并执行相应的回调函数。

如果我们想在其他的按键上面绑定事件怎么办呢?
我们可以使用按键原始的key值去绑定,但注意要转化为kebeb-case(短横线命名)

举个例子:我们想给切换大小写的键绑定一个事件。那么我们就想知道切换大小写键的key值是多少,我们可以利用键盘事件对象的key属性去查询。
在这里插入图片描述
在这里插入图片描述
前面那一个就是key值,得到之后我们不能直接使用,还要转化为短横线命名法:caps-lock,再去使用就可以了。

<div id="root">
	<h2>欢迎来到CSDN学习</h2>
	<input type="text" placeholder="按下回车提示输入" @keydown.caps-lock="showInfo">
</div>

其实我们也可以使用keycode去绑定事件:
在这里插入图片描述
但是这种方法是不被支持的,因为:
在这里插入图片描述
所以我们最好通过按键的名字去绑定事件

换行 => tab (特殊,必须配合keydown去使用)
因为tab键还有一个功能就是转换焦点。比如你选中了一个文本框,按下tab之后,文本框会失去焦点,呈现未选中的状态,此时的焦点已经它的身上转移了。
当你在按下tab的时候,还没有等他弹起来焦点就已经被切换了,这样事件就触发不了。所以要使用keydown去绑定才有用。

在这里有四个键较为特殊:系统修饰键(ctrl、alt、shift、meta)

meta键就是win键

  • 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
  • 配合keydown使用:正常触发事件。

拓展:如果我们想要按下ctrl+y时候才触发事件怎么办?
如果像下面这样:

<div id="root">
	<h2>欢迎来到CSDN学习</h2>
	<input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo">
</div>

那么我们使用ctrl+任意键都可以触发这个事件,显然不符合要求。我们可以这样写:

<div id="root">
	<h2>欢迎来到CSDN学习</h2>
	<input type="text" placeholder="按下回车提示输入" @keydown.enter.y="showInfo">
</div>

一般只有系统修饰键才会这么写

同时Vue还支持别名的定制

Vue.config.keyCodes.huiche = 13 //定义了一个别名按键

然后我们就可以使用了

<div id="root">
	<h2>欢迎来到CSDN学习</h2>
	<input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInfo">
</div>