为了方便大家写代码,vue.js给大家提供了很多方便的修饰符,比如我们经常用到的取消冒泡,阻止默认事件等等

表单修饰符

.lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步:

1
2
3
4
5
6
7
8
9
<div>
<input type="text" v-model="value">
<p>{{value}}</p>
</div>

<div>
<input type="text" v-model.lazy="value">
<p>{{value}}</p>
</div>

这样只有当我们光标离开输入框的时候,它才会更新视图,相当于在onchange事件触发更新。

.trim

我们经常需要过滤一下一些输入框中无意键入的空格,这时可以给v-model添加trim修饰符。

1
<input type="text" v-model.trim="value">

.number

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:

1
<input v-model.number="age" type="number">

如果你先输入数字,那它就会限制你输入的只能是数字。
如果你先输入字符串,那它就相当于没有加.number

事件修饰符

.stop

由于事件冒泡的机制,我们给元素绑定点击事件的时候,也会触发父级的点击事件。

1
2
3
4
5
6
7
8
9
<div @click="test(2)">
<button @click="test(1)">ok</button>
</div>
//js
test(e){
console.log(e)
}
//1
//2

给click事件绑定stop修饰符可以一键阻止事件冒泡,相当于调用了event.stopPropagation()方法。

1
2
3
4
<div @click="test(2)">
<button @click.stop="test(1)">ok</button>
</div>
//1

.prevent

用于阻止事件的默认行为,例如,当点击提交按钮时阻止对表单的提交。相当于调用了event.preventDefault()方法。

1
2
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

注意:修饰符可以同时使用多个,但是可能会因为顺序而有所不同。
用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
也就是从左往右判断。

.self

只当事件是从事件绑定的元素本身触发时才触发回调。像下面所示,刚刚我们从.stop时候知道子元素会冒泡到父元素导致触发父元素的点击事件,当我们加了这个.self以后,我们点击button不会触发父元素的点击事件test,只有当点击到父元素的时候(蓝色背景)才会test~从这个self的英文翻译过来就是‘自己,本身’可以看出这个修饰符的用法

1
2
3
<div class="blue" @click.self="test(2)">
<button @click="test(1)">ok</button>
</div>

.once

这个修饰符绑定了事件以后只能触发一次,第二次就不会触发。

1
<button @click.once="test(1)">ok</button>

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

.capture

从上面我们知道了事件的冒泡,其实完整的事件机制是:捕获阶段–目标阶段–冒泡阶段。
默认的呢,是事件触发是从目标开始往上冒泡。
当我们加了这个.capture以后呢,我们就反过来了,事件触发从包含这个元素的顶层开始往下触发。

1
2
3
4
5
6
7
8
9
10
11
12
13
<div @click.capture="test(1)">
obj1
<div @click.capture="test(2)">
obj2
<div @click="test(3)">
obj3
<div @click="test(4)">
obj4
</div>
</div>
</div>
</div>
// 1 2 4 3

从上面这个例子我们点击obj4的时候,就可以清楚地看出区别,obj1,obj2在捕获阶段就触发了事件,因此是先1后2,后面的obj3,obj4是默认的冒泡阶段触发,因此是先4然后冒泡到3。

.passive

当我们在监听元素滚动事件的时候,会一直触发onscroll事件,在pc端是没啥问题的,但是在移动端,会让我们的网页变卡,因此我们使用这个修饰符的时候,相当于给onscroll事件整了一个.lazy修饰符

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

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

.native

我们经常会写很多的小组件,有些小组件可能会绑定一些事件,但是,像下面这样绑定事件是不会触发的

1
<My-component @click="test(3)"></My-component>

必须使用.native来修饰这个click事件(即),可以理解为该修饰符的作用就是把一个vue组件转化为一个普通的HTML标签,

注意:使用.native修饰符来操作普通HTML标签是会令事件失效的

v-bind修饰符

.sync(2.3.0+ 新增)

在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源。

这也是为什么我们推荐以 update:myPropName 的模式触发事件取而代之。举个例子,在一个包含 title prop 的假设的组件中,我们可以用以下方法表达对其赋新值的意图:

1
this.$emit('update:title', newTitle)

然后父组件可以监听那个事件并根据需要更新一个本地的数据属性。例如:

1
2
3
4
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>

为了方便起见,我们为这种模式提供一个缩写,即 .sync 修饰符:

1
<text-document v-bind:title.sync="doc.title"></text-document>

:title.sync=”isShow”其实是 @update:title=”tmp=>title=tmp”语法糖。是其一种简写形式。

注意带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的)。取而代之的是,你只能提供你想要绑定的属性名,类似 v-model。

当我们用一个对象同时设置多个 prop 的时候,也可以将这个 .sync 修饰符和 v-bind 配合使用:

1
<text-document v-bind.sync="doc"></text-document>

这样会把 doc 对象中的每一个属性 (如 title) 都作为一个独立的 prop 传进去,然后各自添加用于更新的 v-on 监听器。

将 v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync=”{ title: doc.title }”,是无法正常工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑。

.prop

要学习这个修饰符,我们首先要搞懂两个东西的区别。
Property:节点对象在内存中存储的属性,可以访问和设置。
Attribute:节点对象的其中一个属性( property ),值是一个对象,可以通过点访问法 document.getElementById(‘xx’).attributes 或者 document.getElementById(‘xx’).getAttributes(‘xx’) 读取,通过 document.getElementById(‘xx’).setAttribute(‘xx’,value) 新增和修改。
在标签里定义的所有属性包括 HTML 属性和自定义属性都会在 attributes 对象里以键值对的方式存在。

例如:

1
<input id="pwd" type="password" autocomplete="on" name="password" placeholder="密码" class="el-input__inner" maxlength="32">

打印的 attribute 对象(NamedNodeMap 对象表示元素属性节点的无序集合):
对象(NamedNodeMap

v-bind 默认绑定到 DOM 节点的 attribute 上,使用 .prop 修饰符后,会绑定到 property

注意事项
  • 使用 property 获取最新的值;
  • attribute 设置的自定义属性会在渲染后的 HTML 标签里显示,property 不会。
修饰符用途

通过自定义属性存储变量,避免暴露数据
防止污染 HTML 结构

例如:

1
2
3
4
5
6
7
8
9
<input id="input" type="foo" value="11" :data="inputData"></input>
// 标签结构: <input id="input" type="foo" value="11" data="inputData 的值"></input>
// input.data === undefined
// input.attributes.data === this.inputData

<input id="input" type="foo" value="11" :data.prop="inputData"></input>
// 标签结构: <input id="input" type="foo" value="11"></input>
// input.data === this.inputData
// input.attributes.data === undefined

参考资料

Vue官方教程
Vue修饰符