??Vue事件監(jiān)聽的方式貌似違背了關注點分離(separation of concern)的傳統理念。實際上,所有的Vue.js事件處理方法和表達式都嚴格綁定在當前視圖的ViewModel上,它不會導致維護上的困難,使用v-on有以下好處:
1、掃一眼HTML模板便能輕松定位在JS代碼里對應的方法。
2、無須在JS里手動綁定事件,ViewModel代碼可以是非常純粹的邏輯,和DOM完全解耦,更易于測試。
3、當一個ViewModel被銷毀時,所有的事件處理器都會自動被刪除,無須擔心自己如何清理它們。
事件監(jiān)聽
??通過v-on指令來綁定事件監(jiān)聽器。
<div id="app">
<button v-on:click="counter += 1">增加 1</button>
<p>這個按鈕被點擊了 {{ counter }} 次。</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
counter: 0
}
})
</script>
【方法】
許多事件處理的邏輯都很復雜,所以直接把JS代碼寫在 v-on 指令中有時并不可行,v-on指令可以接收一個定義的方法來調用。
【注意】不應該使用箭頭函數來定義methods函數,因為箭頭函數綁定了父級作用域的上下文,所以this將不會按照期望指向 Vue 實例。
<div id="app">
<button v-on:click="num">測試按鈕</button>
<p>{{message}}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data:{
counter:0,
message:''
},
methods: {
num: function (event) {
if (event) {
this.message = event.target.innerHTML + '被按下' + ++this.counter + '次';
}
}
}
})
</script>
【內聯語句】
除了直接綁定到一個方法,也可以用內聯JS語句。
<div id="app">
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
<p>{{message}}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data:{
message:''
},
methods: {
say: function (message) {this.message = message;}
}
})
</script>
??有時也需要在內聯語句處理器中訪問原生 DOM 事件,可以用特殊變量 $event 把它傳入方法 。
<div id="app">
<button v-on:click="say('hi',$event)">Say hi</button>
<button v-on:click="say('what',$event)">Say what</button>
<p>{{message}}</p>
</div>
<script>
var example = new Vue({
el: '#app',
data:{
message:''
},
methods: {
say: function (message,event) {
if(event){
event.preventDefault();
}
this.message = message;
}
}
})
</script>
事件修飾符
??在事件處理程序中調用event.preventDefault()或event.stopPropagation()是非常常見的需求。盡管可以在methods中輕松實現這點,但更好的方式:methods只有純粹的數據邏輯,而不是去處理 DOM 事件細節(jié)。
為了解決這個問題, Vue.js 為v-on提供了事件修飾符,通過由點(.)表示的指令后綴來調用修飾符。
.stop 阻止冒泡
.prevent 阻止默認事件
.capture 使用事件捕獲模式
.self 只在當前元素本身觸發(fā)
.once 只觸發(fā)一次
下面是一些例子
<!-- 阻止單擊事件冒泡 -->
<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>
<!-- 只當事件在該元素本身(比如不是子元素)觸發(fā)時觸發(fā)回調 -->
<div v-on:click.self="doThat">...</div>
<!-- 點擊事件將只會觸發(fā)一次 -->
<a v-on:click.once="doThis"></a>
[注意]使用修飾符時,順序很重要;相應的代碼會以同樣的順序產生。因此,用 @click.prevent.self 會阻止所有的點擊,而 @click.self.prevent 只會阻止元素上的點擊。
【stop】
阻止冒泡
<div id="app" @click="setVal1" style="border:1px solid black;width:300px;">
<button @click="setVal">普通按鈕</button>
<button @click.stop="setVal">阻止冒泡</button>
<button @click="reset">還原</button>
<div>{{result}}</div>
</div>
<script>var vm = new Vue({
el: '#app',
data:{
result:''
},
methods:{
setVal(event){
this.result+=' 子級 ';
},
setVal1(){
this.result+=' 父級 ';
},
reset(){
history.go()
}
}
})
</script>
【prevent】
取消默認事件
<div id="app">
<a target="_blank">普通鏈接</a>
<a @click.prevent target="_blank">取消默認行為</a>
</div>
<script>
var vm = new Vue({
el: '#app'
})
</script>
【capture】
事件捕獲模式
<div id="app" @click.capture="setVal1" style="border:1px solid black;width:300px;">
<button @click.capture="setVal">事件捕獲</button>
<button @click="reset">還原</button>
<div>{{result}}</div>
</div>
<script>var vm = new Vue({
el: '#app',
data:{
result:''
},
methods:{
setVal(event){
this.result+=' 子級 ';
},
setVal1(){
this.result+=' 父級 ';
},
reset(){
history.go()
}
}
})
</script>
【self】
<div id="app">
<div @click="setVal" :style="styleObj1">
<div :style="styleObj2">普通</div>
<button @click="reset">還原</button>
</div>
<div @click.self="setVal" :style="styleObj1">
<div :style="styleObj2">self</div>
<button @click="reset">還原</button>
</div>
</div>
<script>
var styleObj1 = {
display:'inline-block',
height:'60px',
width:'120px',
'background-color': 'lightblue'
};
var styleObj2 = {
display:'inline-block',
height:'30px',
width:'60px',
'background-color': 'lightgreen'
};
var vm = new Vue({
el: '#app',
data:{
styleObj1:styleObj1,
styleObj2:styleObj2
},
methods:{
setVal(event){
event.target.style.outline="solid"
},
reset(){
history.go()
}
}
})
</script>
【once】
只觸發(fā)一次
<div id="app">
<button @click="setVal">普通按鈕</button>
<button @click.once="setVal">觸發(fā)一次</button>
<button @click="reset">還原</button>
<div>{{result}}</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data:{
result:''
},
methods:{
setVal(event){
this.result+=' 內容 ';
},
reset(){
history.go()
}
}
})
</script>