Vue事件修饰符

152 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

事件修饰符

Vue提供了一些事件修饰符来应对事件中遇到的一些常见问题,种类如下:

  • stop:阻止事件冒泡
  • prevent:组织默认行为
  • capture:添加事件侦听器时使用事件捕获模式
  • self:只当事件元素在该元素本身(比如不是子元素)触发时触发回调
  • once:使事件只触发一次

\

stop

<div id="app" style="width: 150px;height: 150px;background-color: red;" @click="divClick">
  <input type="button" value="按钮" @click="btnClick"/>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  var app = new Vue({
    el: '#app',
    data: {

    },
    methods: {
      divClick(){
        alert("点击了DIV");
      },
      btnClick(){
        alert("点击了按钮");
      }
    },
  });
</script>

在该页面中,有一个按钮存在于div中:

由于事件冒泡机制,在点击按钮时,会先触发按钮的事件,还会触发div的点击事件,但有些场景下,我们并不想在点击的按钮时触发父标签的事件,为此,可以使用stop来阻止事件的冒泡:

<input type="button" value="按钮" @click.stop="btnClick"/>

prevent

<div id="app">
  <a href="http://www.baidu.com" @click="aClick">百度一下</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  var app = new Vue({
    el: '#app',
    data: {

    },
    methods: {
      aClick(){
        alert("点击了超链接");
      }
    },
  });
</script>

在该页面中有一个超链接,点击它会跳转至百度首页,然而该超链接绑定了一个点击事件,但因为超链接的跳转性质,使得点击事件无法触发,为此,可以使用prevent来阻止超链接的默认行为:

<a href="http://www.baidu.com" @click.prevent="aClick">百度一下</a>

capture

仍然是对于第二个例子:

通过capture能够修改事件监听器为捕获模式,默认是冒泡机制,如果使用了capture,可以使事件从外向里传递:

<div id="app" style="width: 150px;height: 150px;background-color: red;" @click.capture="divClick">
  <input type="button" value="按钮" @click="btnClick" />
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  var app = new Vue({
    el: '#app',
    data: {

    },
    methods: {
      divClick() {
        alert("点击了DIV");
      },
      btnClick() {
        alert("点击了按钮");
      }
    },
  });
</script>

此时点击按钮将会先弹出点击了DIV,然后弹出点击了按钮。

self

<div id="app" style="width: 150px;height: 150px;background-color: red;" @click.self="divClick">
  <input type="button" value="按钮" @click="btnClick" />
</div>

self表示只有自身触发的事件才会执行回调方法,比如该页面中,如果点击按钮,则会触发按钮的点击事件,由于事件的冒泡机制,外层的div也会触发点击事件,但因为外层div使用了self,不是自己触发的事件,所以div的点击事件不会被触发。

once

该修饰符能保证事件只触发一次:

<div id="app">
  <a href="http://www.baidu.com" @click.prevent.once="aClick">百度一下</a>
</div>

事件修饰符能够组合使用,在该页面中的超链接被设置为阻止默认行为一次,则第一次点击会触发aClick点击事件,接下来再点击就会跳转至百度首页。

双向数据绑定

通过前面的学习,我们了解到v-text、v-html、v-bind能够将data中的数据显示到DOM中,然而这只是一个单向数据绑定的过程,即:data中的数据被绑定到了DOM中,而DOM中数据的改变并不能影响data中的数据,例如:

<div id="app">
  <input type="text" :value="msg"/>
  <input type="text" :value="msg"/>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  var app = new Vue({
    el: '#app',
    data: {
      msg: 'Hello Vue!'
    },
  });
</script>

效果如下:

两个input框均绑定了msg数据,但是这两个框内容的修改互不影响,为了实现数据的双向绑定,可以使用v-model指令:

<div id="app">
  <input type="text" v-model="msg"/>
  <input type="text" v-model="msg"/>
</div>

效果如下:

这两个输入框的值会同步更新,因为输入框内容的修改会影响到data中msg的值,这就是数据的双向绑定;但需要注意一点,v-model指令只能用于表单元素。

过滤器

现有一个显示日期的label:

<div id="app">
  <label>{{new Date()}}</label>
</div>

效果如下:

这显然不是一个友好的日期显示,为此,我们可以使用Vue提供的过滤器来格式化日期:

<div id="app">
  <label>{{new Date() | dateFormat}}</label>
</div>

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

<script>
  // 定义全局的过滤器
  Vue.filter('dateFormat', function (dateStr) {
    // 根据时间字符串构建Date对象
    var dt = new Date(dateStr);
    // 获取年、月、日
    var year = dt.getFullYear();
    var month = dt.getMonth() + 1;
    var day = dt.getDate();
    // 格式化日期
    return `${year}-${month}-${day}`;
  });

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

通过Vue.filter()定义全局的过滤器,提供两个参数,第一个参数为过滤器的名字,第二个参数为过滤器需要处理的逻辑代码,在该函数内正确处理日期并返回即可;

然后在使用过程中需要注意,过滤器采用管道符 | 连接需要处理的数据,管道符后跟过滤器的名字,此时管道符前面的数据将会作为过滤器的处理函数的参数。

\

在调用过滤器进行处理时,也可以继续传入别的参数,比如:

<label>{{new Date() | dateFormat('yyyy-mm-dd')}}</label>
<script>
  Vue.filter('dateFormat', function (dateStr,pattern) {
    ......
  });
</script>

这种通过Vue.filter()的方式定义的过滤器为全局过滤器,是对所有的Vue实例均起作用的,当然了,我们还可以定义仅作用于当前Vue实例的私有过滤器:

<script>
  var app = new Vue({
    el: '#app',
    data: {
    },
    filters: {
      // 定义私有过滤器
      dateFormat: function (dateStr) {
        // 根据时间字符串构建Date对象
        var dt = new Date(dateStr);
        // 获取年、月、日
        var year = dt.getFullYear();
        var month = dt.getMonth() + 1;
        var day = dt.getDate();
        // 格式化日期
        return `${year}-${month}-${day}`;
      }
    }
  });
</script>

若是同时存在私有过滤器和全局过滤器,则默认使用私有过滤器(就近原则)。

按键修饰符

一般网站都具有回车确认填写信息的功能,我们来模拟一下:

<div id="app">
  <input type="text" v-model="msg" @keyup.enter="add">
  <p>{{result}}</p>
</div>

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

<script>
  var app = new Vue({
    el: '#app',
    data: {
      msg: '',
      result:''
    },
    methods: {
      add(){
        this.result = this.msg;
      }
    },
  });
</script>

效果如下:

当在输入框输入内容并按下回车后,下方便会显示输入的内容,这是因为我们设置了输入框的键盘点击事件,而通过按键修饰符则可以精确控制键盘按下哪个键后会触发回调函数,比如这里的 .enter ,它表示回车键。

其它的按键修饰符如下:

  • .tab
  • .delete
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

这些是Vue为方便开发,自己定义的一些常用修饰符,对于别的按键,我们只能用对应的关键字码进行设置:

<input type="text" v-model="msg" @keyup.113="add">

113对应按键 F2 ,此时点击F2就会触发回调函数。

为了便于区分,我们也可以为这些关键字码设置别名:

<script>
  // 定义按键修饰符
  Vue.config.keyCodes = {
    "F1": 113,
  };
</script>

此时使用别名即可:

<input type="text" v-model="msg" @keyup.f2="add">