Vue 0基础学习路线-对比React(3)—— 图解深度详述Vue事件基础入门及v-on和简写形式、事件绑定格式、this对象、事件对象和事件、按键修饰符(附详细案例代码解析过程及版本迭代过程)

1. 重点提炼

  • 事件
  • v-on
    • 简写:@
    • 绑定格式:v-on:click=“函数/表达式”
    • this 对象
    • 事件对象

2. 事件

vue 中,事件通过指令 v-on 进行绑定,v-on 缩写 @

<组件 v-on:事件名称="表达式" />
<组件 @事件名称="表达式" />

2.1 example01

2.1.1 example01-1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>
 
<div id="app">
 
<!--  @click="..." 里不要写if,它不支持  -->
    <button @click="v1++">按钮</button>
    {{v1}}
</div>
 
<script src="./js/vue.js"></script>
<script>
 
    let app = new Vue({
        el: '#app',
        data: {
            v1: 1
        }
    });
</script>
 
</body>
</html>

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.43
Branch: branch01

commit description:a0.43(example01-1——事件的简单使用)

tag:a0.43

2.1.2 example01-2

以上是简单形式,但通常是需要绑定函数的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>

<div id="app">

    <!--  @click="..." 里不要写if,它不支持  -->
    <button @click="v1++">按钮</button>
    {{v1}}

    <hr>
    <button @click="fn">按钮</button>
</div>

<script src="./js/vue.js"></script>
<script>
    function fn() {
        console.log(1);
    }

    let app = new Vue({
        el: '#app',
        data: {
            v1: 1
        }
    });
</script>

</body>
</html>

但是报错了。没有找到fn,因此不要觉得是全局数据就直接可以在vue中使用了。

image-20200622105119349

如定义全局变量,也是找不到的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>

<div id="app">

    <!--  @click="..." 里不要写if,它不支持  -->
    <button @click="v1++">按钮</button>
    {{v1}}

    <hr>
    <button @click="fn">按钮</button>
    {{v2}}
    
</div>

<script src="./js/vue.js"></script>
<script>
    function fn() {
        console.log(1);
    }
    let v2 = 100;

    let app = new Vue({
        el: '#app',
        data: {
            v1: 1
        }
    });
</script>

</body>
</html>

全局变量,vue也是拿不到的,会报错。

image-20200622105334876

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.44
Branch: branch01

commit description:a0.44(example01-2——事件的注意事项)

tag:a0.44

2.1.3 example01-3

全局函数式不能直接绑定,但是针对一些特殊内置函数和对象是可以的

    <button @click="v1++">按钮</button>
    {{v1}}
 
    <hr>
    <button @click="fn">按钮</button>
    {{v2}}
    {{Math.random()}}

数据都需要挂载Vue对象下的,不是全局的变量或者函数就可以直接使用的,但是针对系统的函数(如:math下的函数)除外。

image-20200622105544755

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.45
Branch: branch01

commit description:a0.45(example01-3——事件的可绑定内置函数)

tag:a0.45

3. 组件的 methods 选项

在组件选项中,提供了一个 methods 选项,用来存放组件中使用的函数方法,且存放在 methods 中的函数方法可以通过组件实例(this)进行访问。

3.1 example02

3.1.1 example02-1

vue对象下得函数不能随便放到data中,应该放methods属性中。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>

<div id="app">

    <!--  @click="..." 里不要写if,它不支持  -->
    <button @click="v1++">按钮</button>
    {{v1}}

    <hr>
    <button @click="fn">按钮</button>
    {{v2}}
    {{Math.random()}}

</div>

<script src="./js/vue.js"></script>
<script>

    let app = new Vue({
        el: '#app',
        data: {
            v1: 1,
            v2: 1
        },
        methods: {
            fn(e) {
                this.v2++;
            },
        }
    });
</script>

</body>
</html>

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.46
Branch: branch01

commit description:a0.46(example02-1——事件正确的方式绑定函数)

tag:a0.46

3.1.2 example02-2

为啥点击事件触发Math.random()呢?

这样的改变是vue所期望的。这大概是因为vue2中是用 render(){}方法,当你用vue{{Math.random()}}或其他的vue指令绑定时,包括v-if,当template改变时都会被调用,当用vueclick改变 template时,整个templateDOM将重新计算,所以就又调用了Math.random()重新得到新的值,如果你用datamsg: Math.random() 这样是不会重新计算的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>

<div id="app">

    <!--  @click="..." 里不要写if,它不支持  -->
    <button @click="v1++">按钮</button>
    {{v1}}

    <hr>
    <button @click="fn">按钮</button>
    {{v2}}
    {{msg}}

</div>

<script src="./js/vue.js"></script>
<script>

    let app = new Vue({
        el: '#app',
        data: {
            v1: 1,
            v2: 1,
            msg: Math.random()
        },
        methods: {
            fn(e) {
                this.v2++;
            },
        }
    });
</script>

</body>
</html>

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.47
Branch: branch01

commit description:a0.47(example02-2——解决触发Math.random函数的问题和原理)

tag:a0.47

4. 通过内联方式绑定事件处理函数

<组件 @事件名称="fn" />

<script>
new Vue({
  ...,
  methods: {
  	fn() {
  		//...	
		}
	}
})
</script>
  • 事件绑定函数中的 this 指向组件实例
  • 事件绑定函数中的第一个参数默认为 event 对象
<组件 @事件名称="fn('kaikeba', $event)" />

<script>
new Vue({
  ...,
  methods: {
  	fn(name, ev) {
  		//...	
		}
	}
})
</script>

也可以在事件绑定中直接调用函数(并不会立即执行,也是通过事件触发执行的)

  • 事件对象需要手动传入,名称为 $event

4.1 example03

4.1.1 example03-1

vue中事件函数的this指向该组件实例 => app,不是绑定的元素,主要方便调用组件里其他的东西,如数据,一些其他的特性等。

默认情况下,函数的第一个参数是事件对象:event,方便获取事件绑定的元素。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>

<div id="app">

    <!--  @click="..." 里不要写if,它不支持  -->
    <button @click="v1++">按钮</button>
    {{v1}}

    <hr>
    <button @click="fn">按钮</button>
    {{v2}}

</div>

<script src="./js/vue.js"></script>
<script>

    let app = new Vue({
        el: '#app',
        data: {
            v1: 1,
            v2: 1
        },
        methods: {
            fn(e) {
                this.v2++;
                console.log(e);
            },
        }
    });
</script>

</body>
</html>

image-20200728221338242

以上是火狐,我们看一下谷歌:

image-20200728221928351

小结:

vue 中事件函数的this指向该组件实例 : app

默认情况下,函数的第一个参数是事件对象:event

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.48
Branch: branch01

commit description:a0.48(example03-1——事件绑定函数的事件对象)

tag:a0.48

4.1.2 example03-2

通过:style设置列表样式。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>

<div id="app">

    <!--  @click="..." 里不要写if,它不支持  -->
    <button @click="v1++">按钮</button>
    {{v1}}

    <hr>
    <button @click="fn">按钮</button>
    {{v2}}

    <hr>
    <ul>
        <li v-for="user in users" :style="{color: user.checked ? 'red':''}">{{user.username}}</li>
    </ul>

</div>

<script src="./js/vue.js"></script>
<script>

    let app = new Vue({
        el: '#app',
        data: {
            v1: 1,
            v2: 1,
            users: [
                {id: 1, username: 'zs', checked: true},
                {id: 2, username: 'ls', checked: false},
                {id: 3, username: 'ww', checked: false}
            ]
        },
        methods: {
            fn(e) {
                this.v2++;
                console.log(e);
            },
        }
    });
</script>

</body>
</html>

image-20200728222208271

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.49
Branch: branch01

commit description:a0.49(example03-2——通过:style设置列表样式。)

tag:a0.49

4.1.3 example03-3

也可利用class属性和样式表进行修改。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .checked {
            background: red;
            color: white;
        }
    </style>
</head>
<body>

<div id="app">

    <!--  @click="..." 里不要写if,它不支持  -->
    <button @click="v1++">按钮</button>
    {{v1}}

    <hr>
    <button @click="fn">按钮</button>
    {{v2}}

    <hr>
    <ul>
        <li v-for="user in users" :class="{'checked': user.checked}">{{user.username}}</li>
    </ul>

</div>

<script src="./js/vue.js"></script>
<script>

    let app = new Vue({
        el: '#app',
        data: {
            v1: 1,
            v2: 1,
            users: [
                {id: 1, username: 'zs', checked: true},
                {id: 2, username: 'ls', checked: false},
                {id: 3, username: 'ww', checked: false}
            ]
        },
        methods: {
            fn(e) {
                this.v2++;
                console.log(e);
            },
        }
    });
</script>

</body>
</html>

image-20200728222946114

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.50
Branch: branch01

commit description:a0.50(example03-3——利用class属性和样式表进行修改。)

tag:a0.50

4.1.4 example03-4

但是,如果该函数不是直接被事件调用,而是被间接调用,需要传参数,看列表例子。

实现点击哪个,哪个就高亮。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .checked {
            background: red;
            color: white;
        }
    </style>
</head>
<body>

<div id="app">

    <!--  @click="..." 里不要写if,它不支持  -->
    <button @click="v1++">按钮</button>
    {{v1}}

    <hr>
    <button @click="fn">按钮</button>
    {{v2}}

    <hr>
    <ul>
        <li
                v-for="user in users"
                :class="{'checked': user.checked}"
                @click="doCheck(user, $event)"
        >
            <!--  注意调用事件函数,事件对象需要手动传,并且$event是固定写法    -->
            {{user.username}}
        </li>
    </ul>

</div>

<script src="./js/vue.js"></script>
<script>

    let app = new Vue({
        el: '#app',
        data: {
            v1: 1,
            v2: 1,
            users: [
                {id: 1, username: 'zs', checked: true},
                {id: 2, username: 'ls', checked: false},
                {id: 3, username: 'ww', checked: false}
            ]
        },
        methods: {
            fn(e) {
                this.v2++;
                console.log(e);
            },
            doCheck(user, e) {
                console.log(e)
                user.checked = !user.checked;
            }
        }
    });
</script>

</body>
</html>

image-20200728223610499

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.51
Branch: branch01

commit description:a0.51(example03-4——实现点击哪个,哪个就高亮。)

tag:a0.51

5. 事件修饰符

在事件函数中,我们可以通过 ev.preventDefault()ev.stopPropagation() 来阻止默认行为,阻止冒泡,但是中 vue 中提供一些更加方便的方式来处理这些问题,这就是事件修饰符。

5.1 .stop

阻止事件冒泡

5.1.1 example04

5.1.1.1 example04-1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
<div id="app">
    <div style="padding: 50px; background: red" @click="fn1">
        <button @click="fn2">按钮</button>
    </div>
 
</div>
 
<script src="./js/vue.js"></script>
<script>
 
 
 
    let app = new Vue({
        el: '#app',
        data: {
        },
        methods: {
 
            fn1() {
                console.log('1111')
            },
 
            fn2(e) {
                console.log('2222')
            }
        }
    });
 
</script>
 
</body>
</html>

点击div,正常触发事件。

但是点击按钮会触发父级事件,按钮事件冒泡了。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.52
Branch: branch01

commit description:a0.52(example04-1——按钮事件冒泡)

tag:a0.52

5.1.1.2 example04-2

原生代码解决:e.stopPropagation()=> 原生js禁止事件冒泡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <div style="padding: 50px; background: red" @click="fn1">
        <button @click="fn2">按钮</button>
    </div>

</div>

<script src="./js/vue.js"></script>
<script>



    let app = new Vue({
        el: '#app',
        data: {
        },
        methods: {

            fn1() {
                console.log('1111');
            },

            fn2(e) {
                console.log('2222');
                e.stopPropagation();
            }
        }
    });

</script>

</body>
</html>

但是可能fn2被用到其他事件,那里不需要禁止冒泡,这不就冲突了吗?

这种写法不太好。我们看看vue提供的便捷方式:

<div id="app">
    <div style="padding: 50px; background: red" @click="fn1">
        <button @click.stop="fn2">按钮</button>
    </div>
</div>

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.53
Branch: branch01

commit description:a0.53(example04-2——按钮事件VUE阻止事件冒泡)

tag:a0.53

5.2 .prevent

阻止默认行为

5.2.1 example05

禁止右键默认菜单

<div style="padding: 50px; background: red" @click="fn1" @contextmenu.prevent>

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.54
Branch: branch01

commit description:a0.54(example05——按钮事件VUE阻止默认行为)

tag:a0.54

5.3 .self

只当事件是从侦听器绑定的元素本身触发时才触发回调。

只有自己才这么做,即仅限自己执行。

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

5.3.1 example06

5.3.1.1 example06-1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <div style="padding: 50px; background: red" @click="fn1" @contextmenu.prevent>
        <button @click.stop="fn2">按钮</button>
        <button>111</button>
        <button>222</button>
        <button>333</button>
    </div>

</div>

<script src="./js/vue.js"></script>
<script>



    let app = new Vue({
        el: '#app',
        data: {
        },
        methods: {

            fn1() {
                console.log('1111')
            },

            fn2(e) {
                console.log('2222')
            }
        }
    });
</script>

</body>
</html>

第一个按钮阻止了冒泡,但其余按钮未阻止冒泡。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.55
Branch: branch01

commit description:a0.55(example06-1——多个按钮冒泡)

tag:a0.55

5.3.1.2 example06-2

.stop是针对某个不想冒泡的元素,而这里想子元素都禁止冒泡!全加.stop累死你!

<div style="padding: 50px; background: red" @click.self="fn1" @contextmenu.prevent>
    <button @click="fn2">按钮</button>
    <button>111</button>
    <button>222</button>
    <button>333</button>
</div>

原理其实就是判断一下当前的this和事件源(event.target)是不是同一个,是的话就自己触发。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.56
Branch: branch01

commit description:a0.56(example06-2——.self的使用)

tag:a0.56

5.4 .capture

捕获

添加事件侦听器时使用 capture 模式。

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

5.5 .once

vue 2.1.4 新增

一次绑定,只触发一次回调。

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

不像其它只能对原生的 DOM 事件起作用的修饰符,.once 修饰符还能被用到自定义的组件事件上。

5.6 .passive

(vue2.3.0 新增) 以 { passive: true } 模式添加侦听器

是否允许调用stopprevent

Vue 还对应 addEventListener 中的 passive 选项提供了 .passive 修饰符。

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

这个 .passive 修饰符尤其能够提升移动端的性能。

不要把 .passive.prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你想阻止事件的默认行为。

5.7 注意事项

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

6. 按键修饰符

vue 还提供了许多按键修饰符

6.1 .keyCode

只当事件是从特定键触发时才触发回调。

按哪个键盘,才触发事件

<组件 @keyup.13="fn" />

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

你可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。

<input v-on:keyup.page-down="onPageDown">

在上述示例中,处理函数只会在 $event.key 等于 PageDown 时被调用。

keyCode 的事件用法已经被废弃了并可能不会被最新的浏览器支持。

使用 keyCode attribute 也是允许的:

<input v-on:keyup.13="submit">

为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:

6.2 .enter

<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

6.3 .down

6.4 .exact

vue2.5.0 新增

.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>

7. 原生事件

自定义组件中可以自定义一些事件,可以通过 .native 修饰符来指定监听原生中的事件,而不是组件自定义事件,我们后面说到组件再做说明。



(后续待补充)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值