Vue中的事件绑定和修饰符

目录

@click的方法只写了方法名没括号?

@click方法写上参数

事件的修饰符

@click.prevent

@click.stop与@click.prevent

@click.capture(捕获)

@click.self

@click.prevent.self和@click.self.prevent区别

@click.once

按键修饰符keydown

系统修饰键

鼠标按钮按钮修饰符


 

@click的方法只写了方法名没括号?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue中的事件处理</title>
    <script src="https://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <button @click="handleClick">Button</button>
    </div>
    <script>
        var vm = new Vue({
            el: "#app",
            methods: {
                handleClick(e) {
                    console.log(e);
                }
            }
        })
    </script>
</body>
</html>

点击按钮之后控制台打印如下:

调用方法只写了方法名没写括号,怎么看起来不像是调用方法。但是就是这样调用的,如果我们加上了括号会怎么样呢?

<button @click="handleClick()">Button</button>

点击按钮之后如下:

这样就获取不到事件event对象了,点击直接当成普通函数,传参数为undefined

真的只能放方法名吗?但是我想手动传参数怎么办?

 

@click方法写上参数

<button @click="handleClick">Button</button>

等同于

<button @click="handleClick($event)">Button</button>

带上$event参数是vue内置的事件对象的写法,这和上面只写方法名效果一样。

第二种写法有什么好处呢?这样不但可以传事件对象,还可以传其他参数,来看看

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue中的事件处理</title>
    <script src="https://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <button @click="handleClick($event, 1, 2, 3)">Button</button>
    </div>
    <script>
        var vm = new Vue({
            el: "#app",
            methods: {
                handleClick(e, one, two, three) {
                    console.log(e, one, two, three);
                    console.log(arguments);
                }
            }
        })
    </script>
</body>
</html>

点击按钮之后的运行结果:

 

事件的修饰符

@click.prevent

这个例子并不会跳转到/abc,因为加了事件修饰符prevent,能够阻止事件的默认行为

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue中的事件处理</title>
    <script src="https://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <form action="/abc">
            <input type="submit" @click.prevent/>
        </form>
    </div> 
    <script>
        var vm = new Vue({
            el: "#app",
            methods: {
            }
        })
    </script>
</body>
</html>

vue提供了事件修饰的语法,prevent就是一个事件修饰符,如果还有其他方法,就是@click.prevent="你的方法名",点击后执行方法,但是阻止你的提交行为。

如果不写prevent,那么应该这样实现同样的功能

    <div id="app">
        <form action="/abc">
            <input type="submit" @click="handleClick"/>
        </form>
    </div> 
    <script>
        var vm = new Vue({
            el: "#app",
            methods: {
                handleClick(e) {
                    e.preventDefault();
                }
            }
        })
    </script>

但是这样写就没有好好利用vue的特性了,有修饰符不是更方便嘛

 

@click.stop与@click.prevent

@click.stop 阻止事件冒泡

@click.prevent 阻止事件的默认行为

<a href="http://www.baidu.com" @click.prevent="test4">百度一下</a>   //阻止a标签跳转,仅执行函数test4

<a href="tel:10086" @click.prevent>10086</a> // 阻止拨打电话,这是个坑,在移动端需要注意

另外,href="tel:10086"在ios端点击一次是无法拨打的,很容易被忽略,ios必须长按这里这个链接才会提示是否拨打电话,而在android点一下就可以跳转到拨号页面,ios想和android点一下就拨打需要进一步的处理

<form  action="/xxx"   @submit.prevent="test5">   //阻止表单提交,仅执行函数test5

         <input type="submit" value="注册">
</form>
 

 

@click.capture(捕获)

<div v-on:click.capture="doThis">...</div>
意思就是不加.capture是事件冒泡(默认就是冒泡),加上.capture就是事件捕获,若有多个该修饰符,则由外而内触发。 
就是谁有该事件修饰符,就先触发谁。 

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>事件捕获与冒泡</title>
        <script src="https://unpkg.com/vue"></script>
    </head>
    <body>
        <div id="app">
            <div @click="f1"
                style="width:500px;height:500px;background-color:red">
                <div @click.capture="f2"
                    style="width:300px;height:300px;background-color:green">
                    <div @click.capture="f3"
                        style="width:100px;height:100px;background-color:blue">
                        <div @click="f4"
                            style="width:50px;height:50px;background-color:pink"></div>
                    </div>
                </div>
            </div>
        </div>
        <script>
        var vm = new Vue({
            el: "#app",
            methods: {
                f1() {
                    console.log('==1')
                },
                f2() {
                    console.log('-----2')
                },
                f3() {
                    console.log('===3')
                },
                f4() {
                    console.log('===4')
                }
            }
        })
    </script>
    </body>
</html>

最外层的div:500*500px->red

次外层的div:300*300px->green

中层的div:100*100px->blue

最内层的div:50*50px->pink

这里capture次外层,最内层,所以点击内层触发依次为

-----2
===3
===4
==1

说明:

点击事件先看事件捕获,然后再看事件冒泡

先触发的都是capture(都有capture的情况下从外到内依次触发),其次再是默认冒泡的(由内而外依次触发)

这里优先capture由外到内触发2、3,接着由内到外冒泡 4、1

来一张图

图片描述

 

@click.self

使用.self实现只有点击当前元素的时候,才会触发事件处理函数。即加了.self的元素上e.target === e.currentTarget为true的时候才执行

e.target表示的是点击的元素,而e.currentTarget在事件冒泡或者捕获阶段会变化,比如冒泡时e.currentTarget会不断指向往上冒的对象,而e.target还是最初点击的对象

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>.self</title>
        <script src="https://unpkg.com/vue"></script>
    </head>

    <body>
        <div id="app">
            <div @click.self="handleClick">
                这行内在.self的直接管辖内
                <div @click="hello2">
                    <div @click="hello">hello world</div>
                </div>

            </div>
        </div>
        <script>
            var vm = new Vue({
                el: "#app",
                methods: {
                    handleClick(e) {
                        alert("点击了我.self的直接管辖范围");
                        console.log(".self直接管辖范围内的e.target == e.currentTarget:" + (e.target === e.currentTarget));
                    },
                    hello(e) {
                        console.log("hello world");
                        console.log("hello的div的e.target === e.currentTarget: " + (e.target === e.currentTarget));
                    },
                    hello2(e) {
                        console.log("hello2中间层div的e.target === e.currentTarget: " + (e.target === e.currentTarget));
                    },
                }
            })
        </script>
    </body>

</html>

运行结果如下:


这段代码看到@click.self,这怎么看起来是阻止了冒泡,确实从现象上来看是这样,但是这个应该解释为,点击子元素仍然会冒泡,但是我不接,你只有点击.self直接管辖范围内时候我才执行handleClick(你必须要点我才行,点我的子元素就不行,就算冒泡上来、捕获下去我也都会忽略)

看一下下面代码:

<div id="app" v-on:click.self="close">
    <button>点击</button>
</div>
不管你怎么点击按钮,都不会去执行close方法,因为你的self会忽略冒泡,除非这里的div是@click="close"才会收到子元素的冒泡去执行close方法。

 

@click.prevent.self和@click.self.prevent区别

    <div @click="alert(1)">
      <a href="/#" @click.prevent.self="alert(2)">
        .self直接范围
        <div @click="alert(3)">123123</div>
      </a>
    </div>
// 点击最内层div,会alert3,alert1。不但忽略了alert(2),还阻止了a的默认跳转。
 
// 因为点击的时候会先prevent,阻止默认事件跳转;然后判断是否是.self直接管辖范围的e.target===e.currentTarget是否为true
// 因为点击的最内层的div,所以.self直接管辖范围的e.target===e.currentTarget是false,忽略了alert(2)。
 
    <div @click="alert(1)">
      <a href="/#" @click.self.prevent="alert(2)">
        .self直接范围
        <div @click="alert(3)">123123</div>
      </a>
    </div>
// 点击最内层div,会alert3,alert1,跳转到/#。只忽略了alert(2)。
 
// 这里不会执行alert(2),理由同上,但是可以跳转。

prevent在self前,阻止默认跳转,prevent在self后,那跳转就阻止不了

 

@click.once

once:绑定的事件仅生效一次,然后就解绑。一般与点击事件配合使用,比如@click.once。使得只可以点击一次。

比如:

 <button @click.once='alert("我就第一次出现")'>点击</button>
又比如

<a href="https://www.baidu.com" @click.prevent.once> 第一次点击被阻止</a>

这个链接点击第二次及以后都可以跳转,第一次被阻止

更多事件修饰符可以见官网:事件修饰符

 

按键修饰符keydown

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue中的事件处理</title>
    <script src="https://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <input @keydown="handleKeyDown">
    </div> 
    <script>
        var vm = new Vue({
            el: "#app",
            methods: {
                handleKeyDown() {
                    console.log(e.target.value);
                }
            }
        })
    </script>
</body>
</html>

这里是当按下鼠标的时候就触发handleKeyDown方法,所以按下任意一个键,比如数字1,控制台打印""空串,因为按下的瞬间input框还没有东西。

如果是@keyup则就是松开键盘的一瞬间打印input框里面的值,如果长按“2”,在input不断输入2,放开手,控制台只会打印一次一长串的2。

要注意的是,可能你输入的过快,比如快速分别按下123,则控制台可能会显示3个123,或者一个1,两个123等等情形(在mac都可以复现,在window不会复现)

@keyup.enter松开按键并不会触发,之后按下回车enter的时候才会触发

按键修饰符有

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

更多按键修饰符见官网:按键修饰符

 

系统修饰键

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Vue中的事件处理</title>
        <script src="https://unpkg.com/vue"></script>
    </head>
    <body>
        <div id="app">
            <input @keyup.ctrl="handleKeyUp" />
        </div>
        <script>
        var vm = new Vue({
            el: "#app",
            methods: {
                handleKeyUp(e) {
                    console.log(e.target.value);
                }
            },
        })
    </script>
    </body>
</html>

在input框输入之后,并不会在控制台显示,比如按住ctrl后再输入才会同步到控制台

系统修饰符有

  • .ctrl
  • .alt
  • .shift
  • .meta

更多系统修饰符见官网:系统修饰键

 

鼠标按钮按钮修饰符

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>mouse click</title>
        <script src="https://unpkg.com/vue"></script>
    </head>
    <body>
        <div id="app">
            <div @click.left="handleLeft" @click.right="handleRight">mouse click</div>
        </div>
        <script>
        var vm = new Vue({
            el: "#app",
            methods: {
                handleLeft(e) {
                    console.log("mouse left");
                },
                handleRight(e) {
                    console.log("mouse right");
                }
            },
        })
    </script>
    </body>
</html>

运行结果:

 

关注、留言,我们一起学习。

 

===============Talk is cheap, show me the code================

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页