事件处理
监听事件
可以用v-on
指令监听DOM事件,并在触发时运行一些JavaScript代码。
<div id="example-1">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
var example1 = new Vue({
el: '#example-1',
data: {
counter: 0
}
})
事件处理方法
直接把JavaScript代码写在v-on
指令中是不可行的。因此v-on
还可以接收一个需要调用的方法名称。
<div id="example-2">
<!-- `greet` 是在下面定义的方法名 -->
<button v-on:click="greet">Greet</button>
</div>
var example2 = new Vue({
el: '#example-2',
data: {
name: 'Vue.js'
},
// 在 methods 对象中定义方法
methods: {
greet: function (event) {
// this 在方法里指向当前 Vue 实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
}
})
// 也可以用 JavaScript 直接调用方法
example2.greet() // => 'Hello Vue.js!'
内联处理器中的方法
除了直接绑定到一个方法,也可以在内联JavaScript语句中调用方法。
<div id="example-3">
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
</div>
new Vue({
el: '#example-3',
methods: {
say: function (message) {
alert(message)
}
}
})
有时也需要在内联语句处理器中访问原始的DOM事件。可以用特殊变量$event
把它传入方法。
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
// ...
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) event.preventDefault()
alert(message)
}
}
事件修饰符
在事件处理程序中调用event.preventDefault()
或event.stopPropagation()
是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理DOM事件细节。
为了解决这个问题,Vue.js
为v-on
提供了事件修饰符。修饰符是由点开头的指令后缀来表示的:.stop
、.prevent
、.capture
、.self
、.once
、.passive
。
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在event.target是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用v-on:click.prevent.self
会阻止所有的点击,而v-on:click.self.prevent
只会阻止对元素自身的点击。
不像其它只能对原生的DOM事件起作用的修饰符,.once
修饰符还能被用到自定义的组件事件上。
Vue
还对应addEventListener
中的passive
选项提供了.passive
修饰符。
<!-- 滚动事件的默认行为(即滚动行为)将会立即触发 -->
<!-- 而不会等待onScroll完成 -->
<!-- 这其中包含event.preventDefault()的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
这个.passive
修饰符尤其能够提升移动端的性能。
不要把.passive
和.prevent
一起使用,因为.prevent
将会被忽略,同时浏览器可能会向你展示一个警告。.passive
会告诉浏览器你不想阻止事件的默认行为。
按键修饰符
在监听键盘事件时,我们经常需要检查常见的键值。Vue
允许为v-on
在监听键盘事件时添加按键修饰符。
<!-- 只有在keyCode是13时调用vm.submit() -->
<input v-on:keyup.13="submit">
记住所有的keyCode
比较困难,所以Vue
为最常用的按键提供了别名。
<input v-on:keyup.enter="submit">
<!-- 缩写语法 -->
<input @keyup.enter="submit">
全部的按键别名:.enter
、.tab
、.delete
(捕获“删除”和“退格”键)、.esc
、.space
、.up
、.down
、.left
、.right
。
可以通过全局config.keyCodes
对象自定义按键修饰符别名。
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
自动匹配按键修饰符
也可直接将KeyboardEvent.key
暴露的任意有效按键名转换为短横线分隔来作为修饰符。
<input @keyup.page-down="onPageDown">
在上面的例子中,处理函数仅在$event.key==='PageDown'
时被调用。
有一些按键(.esc
以及所有的方向键)在IE9中有不同的key
值, 如果想支持IE9,它们的内置别名应该是首选。
系统修饰符
可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
.ctrl
、.alt
、.shift
、.meta
。
在Mac系统键盘上,meta
对应command
键(⌘)。在Windows系统键盘meta
对应Windows徽标键(⊞)。
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
修饰键与常规按键不同,在和keyup
事件一起用时,事件触发时修饰键必须处于按下状态。换句话说,只有在按住ctrl
的情况下释放其它按键,才能触发keyup.ctrl
。而单单释放ctrl
也不会触发事件。如果你想要这样的行为,请为ctrl
换用keyCode:keyup.17
。
.exact修饰符
.exact
修饰符允许你控制由精确的系统修饰符组合触发的事件。
<!-- 即使Alt或Shift被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有Ctrl被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>
鼠标按钮修饰符
.left
、.right
、.middle
,这些修饰符会限制处理函数仅响应特定的鼠标按钮。
表单输入绑定
基础用法
可以用v-model
指令在表单<input>
及<textarea>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。
v-model
会忽略所有表单元素的value
、checked
、selected
特性的初始值而总是将Vue
实例的数据作为数据来源。应该通过JavaScript在组件的data
选项中声明初始值。
对于需要使用输入法(如中文、日文等)的语言,v-model
不会在输入法组合文字过程中得到更新。如果想处理这个过程,请使用input
事件。
//文本
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
//多行文本
//在文本区域插值(<textarea></textarea>)并不会生效,应用v-model来代替
<span>Multiline message is:</span>
<p style="white-space:pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>
//单个复选框,绑定到布尔值
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
//多个复选框,绑定到同一个数组
<div id='example-3'>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
new Vue({
el: '#example-3',
data: {
checkedNames: []
}
})
//单选按钮
<div id="example-4">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
</div>
new Vue({
el: '#example-4',
data: {
picked: ''
}
})
//选择框单选时
<div id="example-5">
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
new Vue({
el: '...',
data: {
selected: ''
}
})
//如果v-model表达式的初始值未能匹配任何选项,
//<select>元素将被渲染为“未选中”状态。
//在iOS中,这会使用户无法选择第一个选项。
//因为这样的情况下,iOS不会触发change事件。
//因此,更推荐像上面这样提供一个值为空的禁用选项。
//选择框多选时绑定到一个数组
<div id="example-6">
<select v-model="selected" multiple style="width: 50px;">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Selected: {{ selected }}</span>
</div>
new Vue({
el: '#example-6',
data: {
selected: []
}
})
//用v-for渲染的动态选项
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
el: '...',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
值绑定
对于单选按钮,复选框及选择框的选项,v-model
绑定的值通常是静态字符串 (对于复选框也可以是布尔值)。
<!-- 当选中时,picked为字符串"a" -->
<input type="radio" v-model="picked" value="a">
<!-- toggle为true或false -->
<input type="checkbox" v-model="toggle">
<!-- 当选中第一个选项时,selected为字符串"abc" -->
<select v-model="selected">
<option value="abc">ABC</option>
</select>
但是有时我们可能想把值绑定到Vue
实例的一个动态属性上,这时可以用v-bind
实现,并且这个属性的值可以不是字符串。
复选框
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no">
// 当选中时
vm.toggle === 'yes'
// 当没有选中时
vm.toggle === 'no'
这里的true-value
和false-value
特性并不会影响输入控件的value
特性,因为浏览器在提交表单时并不会包含未被选中的复选框。如果要确保表单中这两个值中的一个能够被提交,(比如yes
或no
),应该用单选按钮。
单选按钮
<input type="radio" v-model="pick" v-bind:value="a">
// 当选中时
vm.pick === vm.a
选择框的选项
<select v-model="selected">
<!-- 内联对象字面量 -->
<option v-bind:value="{ number: 123 }">123</option>
</select>
// 当选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123
修饰符
.lazy
在默认情况下,v-model
在每次input
事件触发后将输入框的值与数据进行同步 (除了输入法组合文字时)。可以添加lazy
修饰符,从而转变为使用change
事件进行同步。
<!-- 在change时而非input时更新 -->
<input v-model.lazy="msg" >
.number
如果想自动将用户的输入值转为数值类型,可以给v-model
添加number
修饰符。
<input v-model.number="age" type="number">
这通常很有用,因为即使在type="number"
时,HTML输入元素的值也总会返回字符串。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给v-model
添加trim
修饰符。
<input v-model.trim="msg">