侧边栏壁纸
  • 累计撰写 122 篇文章
  • 累计创建 68 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

Vue事件绑定及事件修饰符

刘少锋
2020-05-16 / 0 评论 / 0 点赞 / 27 阅读 / 2,147 字

要理解事件绑定,就得先了解事件。

浏览器是事件驱动型的,根据用户的行为触发不同的事件,根据事件执行相应的操作。

事件类型

我们较为熟悉的事件有三大类型:

鼠标键盘事件

鼠标键盘事件事件介绍
onclick鼠标点击某个对象
ondbclick鼠标双击某个对象
onmousedown某个鼠标按键被按下
onmouseup某个鼠标按键被松开
onmousemove鼠标被移动
onmouseover鼠标被移到某元素之上
onmouseout鼠标从某元素移开
onkeypress某个键盘的键被按下或按住
onkeydown某个键盘的键被按下
onkeyup某个键盘的键被松开

页面事件

页面事件事件介绍
onload某个页面或图像被完成加载
onunload用户退出页面
onresize窗口或框架被调整尺寸
onerror当加载文档或图像时发生某个错误
onabort图像加载被中断

表单相关事件

表单相关事件事件介绍
onblur元素失去焦点
onfocus元素获得焦点
onchange用户改变域的内容
onreset重置按钮被点击
onsubmit提交按钮被点击
onselect文本被选定

需要注意的是事件处理程序中的变量event保留着事件对象的信息,包括比如click事件,事件属性里有点击位置相对于浏览器,以及页面的坐标信息,事件的类型(click),触发事件的DOM节点信息等;可以将evenet作为参数传递,在函数内部获取具体的evenet对象信息。

事件绑定

在Vue.js中v-on指令用来监听DOM事件,并在触发事件时运行一些JavaScript代码;当然v-on也可以简写为@

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>事件绑定</title>
    <script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script>
</head>

<body>

    <div id='app'>
        <button v-on:click='func'> 显示 </button>
        <h1> {{msg}} </h1>
    </div>

    <script>
        var vm = new Vue({
            el: '#app',
            data() {
                return {
                    msg: '',
                }
            },
            methods: {
                func() {
                    this.msg = '这是一个大大的H1'
                }
            },
        })
    </script>
</body>

</html>

事件修饰符

Vue.jsv-on 提供了事件修饰符来处理 DOM 事件细节;Vue.js通过由点(.)表示的指令后缀来调用修饰符。

事件修饰符分类

Vue.js提供的事件修饰符主要针对两类情况:

  • 冒泡机制修饰符

    • .stop
    • .capture
    • .self
  • 事件本身修饰符

    • .prevent
    • .once

冒泡机制修饰符

事件冒泡

DOM中,树状结构决定了子元素肯定在父元素里,所以点击子元素,就同时点击了子元素和父元素,以及父元素的父元素,以此类推,当然最终的根节点都是文档,以及window

试想,当一个子元素被点击的时候,不仅仅这个元素本身被点击了,因为这个元素也在其上一级父元素中(属于父级元素的地盘),所以相当于其父元素也被点击了,以此类推,一层一层往外推,最终整个文档也是被点击了,如果每个层级的节点元素都绑定了click事件,那么每个节点的click事件函数都会被执行。举个形象的例子,一个村里的人被打了(click),首先就要按照村里的规矩处理,同时这个村属于某个乡镇,当然也是相当于这个乡镇的人被打了,那么也要按照这个乡镇的规矩处理,以此一层一层往上报。这个例子不准确的地方就是,现实中一个人因为一个事件只会被处理一次,不会因为同一件事情多次处理。

冒泡带来的烦恼

当上层(以及上上层,直至body元素)父级有子元素同样的方法,但你子元素的事件后,所有父级元素的同名函数也会从下到上,由里往外,挨个执行,但是大多数情况下,我们只希望子当事元素事件执行,不希望层层执行,这就要想办法阻止这种冒泡的情况发生。比如我们点击Child Span的时候只显示 Child Span的内容。结合刚刚的例子就是,村里发生了打人事件,在村里解决了,就没必要一层一层往上报,在层层处理了。

事件修饰符

在Vue.js中针对Js事件本身的冒泡机制提供一些事件修饰符以便使用

.stop: 阻止冒泡事件

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>冒泡机制</title>
    <script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script>
    <style>
        #outer {
            width: 400px;
            height: 200px;
            background-color: aqua;
            position: absolute;
        }

        #inner {
            width: 200px;
            height: 100px;
            background-color: darkcyan;
            margin: 50px auto;
        }

        #btn {
            width: 40px;
            height: 30px;
            background-color: gold;
            margin: 35px 80px;
        }
    </style>
</head>

<body>
    <div id='app'>
        <div id="outer" @click='outer'>
            <div id="inner" @click='inner'>
                <button id="btn" @click.stop='btn'>按钮 </button>
            </div>
        </div>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            methods: {
                inner() {
                    console.log("inner触发了")
                },
                outer() {
                    console.log("outer触发了")
                },
                btn() {
                    console.log("btn触发了")
                }
            },
        })
    </script>
</body>

</html>

当点击按钮时,只会触发button本身的click事件,不会继续传递

.self: 只当事件在该元素本身(而不是子元素)触发时触发回调函数

<div id="outer" @click='outer'>
    <div id="inner" @click.self='inner'>
        <button id="btn" @click='btn'>按钮 </button>
    </div>
</div>

当点击按钮时, 继续触发冒泡机制,因此outter盒子同样会触发对应的回调函数,但是inner盒子并不会触发回调函数,只有点击inner本身时,才会正常执行回调函数

.capture: 添加事件侦听器时使用事件捕获模式,即拥有该事件修饰符的元素会优先触发对应事件

<div id="outer" @click.capture='outer'>
    <div id="inner" @click='inner'>
        <button id="btn" @click='btn'>按钮 </button>
    </div>
</div>

当点击按钮时, 继续触发冒泡机制,但是会优先触发outer的回调函数,其次,按照正常的冒泡顺序,由内向外

事件本身修饰符

.prevent:阻止默认行为

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>VueDemo</title>
    <script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script>
    <style>
        form {
            width: 210px;
            height: 300px;

            position: relative;
            margin: 0 auto;
        }

        .user {
            width: 200px;
            height: 20px;
            display: block;
            margin: 5px auto;
        }

        #btn {
            width: 70px;
            float: right;
        }
    </style>
</head>

<body>

    <div id='app'>

        <form action="/userinfo" method="POST" v-on:submit.prevent='onsubmit'>
            <input type="text" name="user" class="user" v-model='user.name' placeholder="请输入用户名。。。">
            <input type="password" name="user" class="user" v-model='user.pwd' placeholder="请输入密码。。。">

            <input type="submit" id="btn" value="提交">
        </form>

    </div>

    <script>
        var vm = new Vue({
            el: '#app',
            data() {
                return {
                    user: {
                        name: "",
                        pwd: ""
                    }
                }
            },
            methods: {
                onsubmit() {
                    console.log(`表单信息:${this.user.name}和${this.user.pwd}提交`)
                }
            },
        })
    </script>
</body>

</html>

表单本身的提交行为会进行页面跳转,现在使用.prevent修饰符之后,只执行绑定的方法,不跳转页面;类似的还有超链接等的默认行为都可以使用该修饰符阻止

.once: 事件只能触发一次

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>VueDemo</title>
    <script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script>
</head>

<body>
    <div id='app'>
        <button @click.once='btn'> 你只能评论一次 </button>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            methods: {
                btn() {
                    alert("已评论")
                }
            },
        })
    </script>
</body>

</html>
0

评论区