事件传参

关于事件处理之前已经接触过v-on,用来监听一个DOM事件然后触发执行JavaScript语句,然而很多事件处理的js代码比较复杂,所以直接写在v-on中会使得整体变得臃肿,所以v-on还可以直接接收一个方法名称,提高了代码的复用性。

原生DOM事件

首先我们了解一下原生DOM事件内容,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1 @click="clickH1">点击查看原生 DOM 事件</h1>
    </div>
</body>
</html>
<script>
    new Vue({
        el:"#app",
        methods: {
            clickH1(e){
                console.log(e)
            }
        },
    })
</script>
  • 第12行绑定点击事件,触发打印原生DOM事件

测试页面:
部分打印内容如下,在e.target下有tagName,表明DOM对象的标签名,其实很多信息都存在了原生的target属性下
image.png

Vue事件传参

上面介绍了打印原生DOM事件出现的内容,现在我们需要实现传递一个值给该标签,当我们点击标签时,直接在控制台输出该值,可以在v-on或者@中使用(实参) 来传递参数给之前的e对象,这样直接覆盖了原生DOM内容。

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1 @click="clickH1(事件1)">点击查看1</h1>
        <h1 @click="clickH1(事件2)">点击查看2</h1>

    </div>
</body>
</html>
<script>
    new Vue({
        el:"#app",
        methods: {
            clickH1(e){
                console.log(e)
            }
        },
    })
</script>
  • 第12、13行在@click中使用括号传递了两个字符串分别为:"事件1"、"事件2"。
  • 接22行是使用形参e接收12、13行括号中传递的参数,而不是之前原生的DOM事件。

测试页面:
image.png

可以看到不是原生DOM事件。

如果想既传递传参,又查看原生DOM事件,使用特殊变量$event传入方法,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1 @click="clickH1(123,$event)">点击打印传递的参数123</h1>
        <h1 @click="clickH1">点击查看原生 DOM 事件</h1>
    </div>
</body>
</html>
<script>
    new Vue({
        el:"#app",
        methods: {
            clickH1(e,event){
                console.log(e);
                console.log(event);
            }
        },
    })
</script>
  • 第12行添加新的参数$event
  • 第21行方法添加形参event接受$event

测试页面:
image.png
观察控制台可以看到传递的参数和原生DOM事件都打印在控制台。

自定义参数名

在模板中,制定传递的参数的参数名,使用data-参数名="value"方法来传递自定义参数,在被调用的函数中,使用$event.currentTarget.dataset.参数名来获取自定义的参数。

例如:

<div id="app">
    <div
    data-id="123"
    @click='add'
    >{{ message }}</div>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data () {
            return {
                message: 'Hello Vue!'
            }
        },
        methods: {
            add(e){
                console.log('currentTarget:',e.currentTarget.dataset);
            }
        }
    })
</script>

运行结果:
image.png
注意:如果@click="函数名"中,函数名不带括号,则会自动注入$event对象,此时e.currentTarget存在,如果带有括号,则需要将$event作为参数,才能访问到$event对象。

事件修饰符

官方文档:
https://cn.vuejs.org/v2/guide/events.html#%E4%BA%8B%E4%BB%B6%E4%BF%AE%E9%A5%B0%E7%AC%A6

事件修饰符是用来对执行事件动作进行一些规定,比如只允许事件执行一次、提交事件不重新加载页面等等。

  • .stop

    • 阻止单击事件传播
  • .prevent

    • 不再重新加载页面
  • .capture

    • 添加事件监听器时使用事件捕获模式
  • .self
  • .once

    • 只允许事件执行一次
  • .passive

并且修饰符可以串联使用,而且需要注意修饰符的先后执行顺序。

.once

.once只允许事件触发一次,如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1 @click="clickH1(123,$event)">点击打印传递的参数123</h1>
        <h1 @click="clickH1">点击查看原生 DOM 事件</h1>
        <button @click.once="clickBtn">按钮</button>
    </div>
</body>
</html>
<script>
    new Vue({
        el:"#app",
        methods: {
            clickH1(e,event){
                console.log(e)
                console.log(event)
            },
            clickBtn(){
                alert(123)
            }
        },
    })
</script>
  • 第14行添加按钮标签,然后使用.once修饰符,绑定clickBtn方法
  • 26-28行新建一个方法触发弹窗事件。

测试页面:

image.png
多次点击按钮,只有第一次触发弹窗事件。

.stop

.stop是用来阻止冒泡事件发生,阻止事件向父级标签传播

了解什么是冒泡事件可以查看之前学习微信小程序的一篇文档:https://www.yuque.com/justinpeiqi/dr9dgm/xdgl1l

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1 @click="clickH1(123,$event)">点击打印传递的参数123</h1>
        <h1 @click="clickH1">点击查看原生 DOM 事件</h1>
        <button @click.once="clickBtn">按钮</button>
        <hr>
        <div class="out" @click="clickOut" style="width: 400px;
                                                  height: 400px;background-color: pink;">
            <div class="box" @click="clickBox" style="width: 100px;
                                                      height: 100px;background: orange;">
            box
            </div>
        </div>
    </div>
</body>
</html>
<script>
    new Vue({
        el:"#app",
        methods: {
            clickH1(e,event){
                console.log(e)
                console.log(event)
            },
            clickBtn(){
                alert(123)
            },
            clickOut(){
                console.log("out")
            },
            clickBox(){
                console.log("box")
            }
        },
    })
</script>
  • 16-22行创建了嵌套的区域,粉色区域包含橙色区域,并且每个区域绑定了各自的方法,当点击区域时会打印对应的内容
  • 37-42行两个方法对应打印各自区域名

在未使用.stop情况下,点击橙色区域,发现橙色和粉色区域事件都触发了,就是说原本只想点击橙色区域,但是橙色被粉色包含,所以事件还传递给了父级粉色,导致粉色事件也触发。image.png

所以有时为了避免冒泡事件的发生,在vue中使用.stop来阻止事件向父级标签传递,这也是面试时的一个常见的问题。

现在添加.stop:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1 @click="clickH1(123,$event)">点击打印传递的参数123</h1>
        <h1 @click="clickH1">点击查看原生 DOM 事件</h1>
        <button @click.once="clickBtn">按钮</button>
        <hr>
        <div class="out" @click="clickOut" style="width: 400px;height: 400px;background-color: pink;">
            <div class="box" @click.stop="clickBox" style="width: 100px;height: 100px;background: orange;">
            box
            </div>
        </div>
    </div>
</body>
</html>
<script>
    new Vue({
        el:"#app",
        methods: {
            clickH1(e,event){
                console.log(e)
                console.log(event)
            },
            clickBtn(){
                alert(123)
            },
            clickOut(){
                console.log("out")
            },
            clickBox(){
                console.log("box")
            }
        },
    })
</script>
  • 第17行添加.stop

添加了.stop阻止事件向外传递,测试页面:
image.png
可以发现点击橙色区域只触发了本区域的事件,而其父级事件没有被触发。

.prevent

.prevent可以用来直接阻止input内容被提交,.prevent也可以绑定方法,等待方法执行完成之后再去提交内容,这样可以使用方法对填写的内容进行验证,比如验证是否为空,验证数据格式是否规范,等验证通过之后再提交至目标对象。

1.0例子

例如以下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1 @click="clickH1(123,$event)">点击打印传递的参数123</h1>
        <h1 @click="clickH1">点击查看原生 DOM 事件</h1>
        <button @click.once="clickBtn">按钮</button>
        <hr>
        <div class="out" @click="clickOut" style="width: 400px;height: 400px;background-color: pink;">
            <div class="box" @click.stop="clickBox" style="width: 100px;height: 100px;background: orange;">
            box
            </div>
        </div>


        <form @submit.prevent="onSubmit">
            <input type="text" v-model="username">
            <input type="submit">
        </form>
    </div>
</body>
</html>
<script>
    new Vue({
        el:"#app",
        data:{
            username:""
        },
        methods: {
            onSubmit(){
                if(this.username.length>2){
                    location.href="http://baidu.com"  // 如果验证了输入框内容长度大于2才能跳转至百度
                }
            },
            clickH1(e,event){
                console.log(e)
                console.log(event)
            },
            clickBtn(){
                alert(123)
            },
            clickOut(){
                console.log("out")
            },
            clickBox(){
                console.log("box")
            }
        },
    })
</script>
  • 23-26行新建一个form表单,并且绑定提交事件,并使用.prevent绑定onSubmit方法

    • 第24行input输入绑定username变量
  • 37-41行新建onSubmit方法,内容是检查username变量的长度

如果输入栏长度不大于2那么就会被.prevent 阻止提交跳转页面。

测试页面:
image.png
当输入栏中只有两位长度时,点击提交按钮,会被拒绝跳转。
只有当输入内容大于3时点击提交按钮才会跳转。

2.0例子

除此之外可以使提交按钮在当输入框内容不符合条件时默认为disable状态,不允许点击按钮。

可以在form表单中绑定input事件,然后对应新建myIpt方法,通过新建一个isShow布尔值,来判断提交按钮是否有效。

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1 @click="clickH1(123,$event)">点击打印传递的参数123</h1>
        <h1 @click="clickH1">点击查看原生 DOM 事件</h1>
        <button @click.once="clickBtn">按钮</button>
        <hr>
        <div class="out" @click="clickOut" style="width: 400px;height: 400px;background-color: pink;">
            <div class="box" @click.stop="clickBox" style="width: 100px;height: 100px;background: orange;">
            box
            </div>
        </div>


        <form @submit.prevent="onSubmit">
            <input type="text" v-model="username" @input="myIpt">
            <input type="submit" :disabled="isShow">
            <h1>{{isShow}}--{{username.length}}</h1>
        </form>
    </div>
</body>
</html>
<script>
    new Vue({
        el:"#app",
        data:{
            username:"",
            isShow:true,
        },
        methods: {
            myIpt(){
                if(this.username.length>2){
                    this.isShow=false  // 如果验证了输入框内容长度大于2按钮才允许点击
                }else{
                    this.isShow=true
                }
            },
            onSubmit(){
                if(this.username.length>2){
                    location.href="http://www.baidu.com"  // 如果验证了输入框内容长度大于2才能跳转至百度
                }
            },
            clickH1(e,event){
                console.log(e)
                console.log(event)
            },
            clickBtn(){
                alert(123)
            },
            clickOut(){
                console.log("out")
            },
            clickBox(){
                console.log("box")
            }
        },
    })
</script>
  • 23-27行为表单

    • 第24行绑定了input事件,并且对应绑定了myIpt方法
    • 第25行将disabled属性绑定isShow布尔值
  • 39-50行对应绑定的方法

测试页面:
当长度小于等于2时,提交按钮不允许点击。
image.png
长度大于2时,提交按钮允许点击。
image.png

按键修饰符

可以让标签监听键盘事件,当用户在输入栏中敲入对应的按键时会调用其绑定的方法。

官方文档:https://cn.vuejs.org/v2/guide/events.html#%E6%8C%89%E9%94%AE%E4%BF%AE%E9%A5%B0%E7%AC%A6

最后修改:2024 年 03 月 13 日
如果觉得我的文章对你有用,请随意赞赏