Vue事件绑定(二)

740 阅读2分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

前言

上一篇我们讲到了Vue的基本配置,有了配置总得搞点东西玩玩是吧。今天来搞搞事件啊,说不多说,直接开搞。

为了简化操作,不用每次都引入vue.js。所以后面如果没有特别说明,都是基于以下模板进行代码的演示,我们上一篇也已经说过了哈。

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style></style>
</head>

<body>
    <!--引入Vue三方库-->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <!--创建一个DOM元素-->
    <div id="app"></div>

    <script>
    // 实例化一个Vue对象
    // Vue 构造函数接收配置对象
    new Vue({
           el: '#app' // el 指定页面中DOM元素,Vue就会以这个DOM为挂载对象
    })
    </script>
</body>

</html>

事件处理

概念 在vue中可以给DOM元素通过 v-on 指令 绑定事件处理函数

语法 v-on:事件名="js表达式"

<div id="app">
     每次点击h2标签 count都会加一
     <h2 v-on:click="count++">{{count}}</h2>
</div>

<script>
        new Vue({
            el: '#app',
            data: {
                count: 17
            }
        })
</script>

注意 v-on: 可以简写为 @ 符号

<div id="app">
        <h2 v-on:click="count++">{{count}}</h2>
        <button @click="count--">minus</button>
</div> 

<script>
        new Vue({
            el: '#app',
            data: {
                count: 17
            }
        })
</script>

------------注意------------

  1. v-on事件绑定中,函数名后不显式添加()会被vue隐式默认添加(),并且会将event事件对象作为参数传入到函数中
<div id="app">
        // 被点击会打印undefined,因为函数没有传递任何参数
        <button @click="clickHandel()">click me</button>
        // 被点击会打印事件对象event,vue会隐式调用该函数并传递event作为当前函数的参数
        <button @click="clickHandel">click me</button>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
        new Vue({
            el: '#app',
            methods: {
                clickHandel(event) {
                    console.log(event)
                }
            }
        })
</script>
  1. 如果需要在事件绑定函数中不但手动传参还要传递event事件对象,需要使用vue实例对象提供的特殊变量$event,将事件对象手动传递给函数内部
<div id="app">
    // 向函数手动传递参数 $event是vue所提供的当前事件对象特殊变量
    <button @click="clickHandel($event,12)">click me</button>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
    new Vue({
        el: '#app',
        methods: {
            clickHandel(event,num) {
                console.log(event,num)
            }
        }
    })
</script>

Vue实例对象的方法

概念 Vue构造函数配置选项中支持methods选项, 该选项可以将当前实例的自定义方法混入到vue实例中。这些方法可以直接通过 Vue 实例访问,或者在指令表达式(例如v-on)中使用。methods定义的方法其 this 自动绑定为 当前Vue 实例。

<div id="app">
    <h2 v-on:click="addCount()">{{count}}</h2>
    <button @click="minusCount()">minus</button>
    // v-on事件绑定中,函数名后不显式添加()会被vue隐式默认添加()
    <h2 v-on:click="addCount">{{count}}</h2>
    <button @click="minusCount">minus</button>
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            count: 17
        },
        methods: {
            addCount() {
                this.count += 2
            },
            minusCount() {
                this.count -= 2
            }
        }
    })
</script>

也许这个例子看的不是很透彻啊,那我们搞个经典的案例玩玩,是什么呢?没错,就是学js的时候写到吐了的轮播图。是不是又惊喜又意外又刺激呢?没错要的就是这样!今天啊,我们就搞个无缝轮播图试试啊。也许样式不是很好看啊,这里我们看效果,样式可以自己回去慢慢鼓捣。

要求

  • 实现无缝轮播图
  • 要求不需要自动轮播,
  • 轮播图中包含两个按钮next(下一张),prev(上一张)实现点击切换实现无缝轮播
  • 无缝轮播图包含pages 小圆点,对应下标小圆点会高亮

效果图

轮播.gif

基本上注释都在代码里,所以我们就直接放代码了。知识点都在上一篇的指令中有谈到;除了一个@transitionend事件之外。简单来说就是为了监听过渡的动画是否完成,可以去官网查阅或者翻一翻菜鸟教程,我们这里就先用着。

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            list-style: none;
        }

        .carousel-wrapper {
            position: relative;
            margin: 20px auto;
            width: 375px;
            height: 157.5px;
            border: 1px solid #555;
            overflow: hidden;
        }

        .carousel {
            width: 1000%;
            height: 100%;
            font-size: 0;
        }

        .carousel li {
            display: inline-block;
            width: 10%;
            height: 100%;
        }

        .carousel li img {
            display: block;
            width: 100%;
            height: 100%;
        }

        .pages {
            display: flex;
            align-items: center;
            justify-content: space-around;
            position: absolute;
            bottom: 0;
            left: 80px;
            width: 200px;
            height: 20px;
            background-color: rgba(7,17,27,.3);
        }

        .pages .dot {
            display: inline-block;
            width: 15px;
            height: 15px;
            border-radius: 50%;
            background-color: rgba(255, 255, 255,0.8);
        }

        .pages .dot.active {
            background-color: #fc0;
        }
    </style>
</head>

<body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <div id="app">
        <div class="carousel-wrapper">
            <!-- 通过绑定style设置切换的动画 -->
            <ul class="carousel" :style="{
                transform: `translateX(${-10 * index}%)`,
                transition: needTransition ?'all .5s linear' : 'none'
            }" @transitionend="transitionEndHandle">
                <!-- 图片换成自己的图片即可 -->
                <li>
                    <img src="./src/05.jpg">
                </li>
                <li>
                    <img src="./src/01.jpg">
                </li>
                <li>
                    <img src="./src/02.jpg">
                </li>
                <li>
                    <img src="./src/03.jpg">
                </li>
                <li>
                    <img src="./src/04.jpg">
                </li>
                <li>
                    <img src="./src/05.jpg">
                </li>
                <li>
                    <img src="./src/01.jpg">
                </li>
            </ul>
            <!-- 小圆点 -->
            <ul class="pages">
                <!-- 绑定class -->
                <li class="dot" :class="{active: index === 1||index === 6}"></li>
                <li class="dot" :class="{active: index === 2}"></li>
                <li class="dot" :class="{active: index === 3}"></li>
                <li class="dot" :class="{active: index === 4}"></li>
                <li class="dot" :class="{active: index === 5||index === 0}"></li>
            </ul>
        </div>
        <div style="text-align: center;">
            <!-- 上一张下一张的按钮 -->
            <button @click="prevPic">prev</button>
            <button @click="nextPic">next</button>
        </div>
    </div>

    <script>
        new Vue({
            el: '#app',
            data: {
                index: 1,
                needTransition: true
            },
            methods: {
                // 下一张的事件
                nextPic() {
                    this.index++
                    this.needTransition = true
                },
                // 上一张的事件
                prevPic() {
                    this.index--
                    this.needTransition = true
                },
                // 动画事件
                transitionEndHandle() {
                    console.log('过渡结束了')
                    // 最后一张没有动画效果的回到第一张
                    if (this.index >= 6) {
                        this.index = 1
                        this.needTransition = false
                    }

                    // 第一张没有动画效果回到最后一张
                    if (this.index <= 0) {
                        this.index = 5
                        this.needTransition = false
                    }
                }
            }
        })
    </script>

</body>

</html>

修饰符

概念在事件处理程序中用 event.preventDefault()event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。简化上面这种DOM事件细节需求

语法 v-on:事件名.修饰符1.修饰符2...

事件修饰符

.stop 阻止事件冒泡

<div id="app">

    <div :style="{width: '200px',height: '200px',backgroundColor: 'red'}" 
         @click="clickHandle($event,'div')">
        <p :style="{width: '120px',height: '120px',backgroundColor: 'green'}"
            @click.stop="clickHandle($event,'p')">
            <a @click.stop="clickHandle($event,'a')">我是A标签</a>
        </p>
    </div>

</div>

<script>
    new Vue({
        el: '#app',
        methods: {
            clickHandle(evet, detail) {
                console.log(detail + '被点击了', event.target)
            }
        }
    })
</script>

.prevent 阻止事件浏览器默认行为

阻止form表单默认提交行为

<form>
    <input @click.prevent="clickHandle($event,'submit')" type="submit">
</form>

.capture 事件使用捕获

<div :style="{width: '200px',height: '200px',backgroundColor: 'red'}" 
     @click.capture="clickHandle($event,'div')">
    <p :style="{width: '120px',height: '120px',backgroundColor: 'green'}"
       @click.capture="clickHandle($event,'p')">
        <a @click="clickHandle($event,'a')">我是A标签</a>
    </p>
</div>

.self event.target必须是绑定事件的元素自身才能触发

<div :style="{width: '200px',height: '200px',backgroundColor: 'red'}" 
     @click="clickHandle($event,'div')">
    <p :style="{width: '120px',height: '120px',backgroundColor: 'green'}"
        @click.self="clickHandle($event,'p')">
        <a @click="clickHandle($event,'a')">我是A标签</a>
    </p>
</div>

.once 事件只触发一次

 <div :style="{width: '200px',height: '200px',backgroundColor: 'red'}" 
      @click="clickHandle($event,'div')">
    <p :style="{width: '120px',height: '120px',backgroundColor: 'green'}"
        @click.self.stop.once="clickHandle($event,'p')">
        <a @click="clickHandle($event,'a')">我是A标签</a>
    </p>
</div>

.passive 提高移动端scroll事件滑动性能的修饰符,该修饰符不能与.prevent 一起使用

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

按键修饰符

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

v-on:事件名.[event.key]

<!-- 按键盘s触发 -->
<textarea @keyup.s="keyUpHandle"></textarea>
<!-- 按键盘a触发 -->
<textarea @keyup.a="keyUpHandle"></textarea>
<!-- 按键盘a或者s触发 -->
<textarea @keyup.a.s="keyUpHandle"></textarea>

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

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

v-on:事件名.系统修饰键.[event.key]

系统修饰键可以配合其他按键一起按下相应按键时才触发鼠标或键盘事件的监听器。

  • .ctrl
  • .alt
  • .shift
  • .meta 在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。在其他特定键盘上,尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品,比如 Knight 键盘、space-cadet 键盘,meta 被标记为“META”。在 Symbolics 键盘上,meta 被标记为“META”或者“Meta”。
// 在按下shift键后再按其他键才会触发
<textarea @keyup.shift="keyUpHandle"></textarea>
// 在按下shift键后按a键才会触发
<textarea @keyup.shift.a="keyUpHandle"></textarea>
// 在按下shift键ctrl键后再按a键才会触发
 <textarea @keyup.shift.ctrl.a="keyUpHandle"></textarea>

注意: vue在2.5.0 新增 .exact 修饰符(严格修饰符),该修饰符的功能是,严格控制系统修饰键按压

//非严格模式下在按下shift键ctrl键后再按a键也会触发
<textarea @keyup.shift.a="keyUpHandle"></textarea>
//严格模式下在按下shift键ctrl键后再按a键不会触发
// 只有仅按shift键没有按下其他系统修饰键的情况下按a才会触发
<textarea @keyup.shift.a.exact="keyUpHandle"></textarea>

鼠标按钮修饰符

概念 鼠标修饰符会限制处理函数仅响应特定的鼠标按钮。

  • .left
  • .right
  • .middle

结尾

今天就先到这里啦!我们下期再见!码字不易,觉得不错的可以动动小指头点点赞啥的哟~

系列文章

Vue系列

Vue-Router系列

Vuex系列