事件處理v-on
用于事件交互。
語法:v-on:要綁定的事件=“事件觸發時執行的函數”?(函數這里可以寫括號,也可以不寫,沒有影響)
簡寫:@:
事件觸發時要執行的函數,在Vue配置參數中,通過methods:{}配置。
<body><div id="root"><button v-on:click="consoleMessage">1</button><button @click="consoleMessage">2</button></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data:{},methods:{consoleMessage(){console.log('hello');}}})</script></body>
傳參、this指向
傳參:事件默認傳遞參數event(也可以不叫這個名字)。如果需要event之外的參數,可以在v-on設置綁定的函數時,以 要綁定的函數名(要傳遞的參數) 格式。和函數傳參是一樣的。
但要注意的是,當自己傳遞了某個參數時,可能無法在綁定的事件里獲取event(取決于當前vue版本的語法)。如果無法獲取event,在傳參時,就要使用$event表示當前位置傳遞event。但如果語法支持,也可以直接使用event獲取。
<button @click="consoleMessage(100,$event)">2</button><button @click="consoleMessage(100)">2</button>
this指向:事件綁定的函數是普通函數的情況下,函數中的this為Vue實例,本例中也就是vm。
如果是寫在Vue組件里,this指向組件。
事件綁定的函數是箭頭函數的情況下,函數中的this為window。
推薦綁定的函數中使用普通函數,不要用箭頭函數。
<body><div id="root"><button v-on:click="consoleMessage('catcat')">1</button><button @click="consoleMessage">2</button></div>...methods:{consoleMessage(name){console.log(`hello ${name}`);console.log(this);}}...
給methods設定的函數,實際上也會被添加到Vue實例上,但事件函數是沒有數據代理的。
如果把事件函數寫在data中,實際上代碼也是可以生效的,但是data中的數據多了一層數據代理,對于不需要代理的數據,最好還是寫在methods中。
事件修飾符
在綁定事件時,如果希望修改事件的某些默認設置,可以使用事件修飾符。
語法:@事件.事件修飾符
Vue中提供的事件修飾符:
.prevent
設置取消事件的默認行為的執行。
以a標簽為例,a標簽默認打開網頁,可以使用click.prevent達成點擊a標簽不會新開網頁的效果。
...<a href="www.baidu.com" @click.prevent="myEvent">goto baidu</a>...methods:{...myEvent(){alert('hello');}}...
.stop
阻止事件冒泡。
比如在一個div里有一個按鈕,當點擊按鈕時,由于按鈕在div內部,點擊事件會同時發生在按鈕和div身上,如果按鈕綁定了click事件,div也綁定了click事件,兩個click事件都會觸發。如果只希望觸發內部按鈕的click事件,不觸發外部div事件,可以使用click.stop。
<body><div id="root"><div class="outerDiv" @click="changeColor"><button class="innerButton" @click="change">click</button></div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data:{},methods:{change(){console.log('change');},changeColor(){console.log('changeColor');}}})</script></body>
點擊button會觸發兩個console。
如果設置click.stop,則只會觸發一個:
如果是多層嵌套結構,有三層div,給內層事件設置.stop:
<body><div id="root"><div class="outerDiv" @click="outer"><div class="midDiv" @click="mid"><button class="innerButton" @click.stop="inner">click</button></div></div></div>...methods:{inner(){console.log('inner');},mid(){console.log('mid');},outer(){console.log('outer');}}})...
對于一個a標簽,如果不希望點擊標簽后頁面跳走,用click.stop是無法阻止頁面跳走的:
雖然.stop可以阻止頁面的冒泡行為,但當在a標簽的click上設置stop時,頁面仍然可以跳走,需要寫click.stop.prevent。事件修飾符可以連寫。
.once
事件只能觸發一次。
設置之后,綁定的事件只有第一次觸發時才生效。再點擊不會生效。(比較好理解這里不寫例子了)
.capture
使用事件捕獲模式。
對于嵌套的div,如果兩個div都綁定了相同的click事件,但每個事件的傳參不一樣。
當點擊一個div時,先進行事件捕獲,事件捕獲由外向內,會先經過outerDiv,再經過innerDiv。捕獲結束后,進行事件冒泡,事件冒泡由內向外,先經過innerDiv,再經過outerDiv。在事件冒泡的階段處理事件。
設置事件捕獲,則事件會在捕獲階段進行處理。
如果想先觸發外層div,click.capture應該放在外層div上。
<body><div id="root"><div class="outter" @click="getData(1)"><div class="inner" @click="getData(2)"></div></div></div></div><style>.outter{background-color: aquamarine;padding: 5px;}.inner{background-color: chocolate;padding: 5px;}</style><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data:{},methods:{getData(data){console.log(data);}}})</script></body>
點擊內部div,返回的順序
給外部div設置捕獲階段觸發,返回的順序:
.self
只有event.target是當前操作的元素時才觸發事件。也就是說,如果代碼存在嵌套結構,事件觸發時(通過冒泡或捕獲觸發),可能事件的觸發并不是由直接對當前標簽進行交互時觸發,是冒泡或捕獲上來的,這種情況下綁定的事件函數不會被觸發。
.passive
事件的默認行為立即執行,無需等待事件回調執行完畢。
這里用一個滾動事件來說明,先回顧一下滾動事件:
overflow:auto。當元素溢出時,出現滾動條。
綁定滾動事件:
@scroll 頁面上的滾動條滑動時觸發,當滾動條到底時,再把滾動條往下拽,事件不會觸發。
@wheel 滾動鼠標的滾輪時觸發,當滑動條到底時,再滾動鼠標滾輪,也會觸發事件。
當執行wheel滾動事件時,會先執行綁定事件內的邏輯,當綁定事件執行完畢后,才執行滾動事件的默認行為(滾動條移動)。因此當滾動事件內部的邏輯運算時間過長時,即使移動滾動條,滾動條也會出現不動的現象。
<body><div id="root"><ul @wheel="getData"><li></li><li></li><li></li></ul></div><style>ul{width: 200px;height: 200px;background-color: aqua;overflow: auto; } li{width: 200px;height: 100px;}</style><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data:{},methods:{getData(){for(let i = 0;i < 1000000;++i){console.log('con');}}}})</script></body>
在這個例子中,由于滾輪滑動觸發的事件內部要執行100萬次,因此即使滑動滑動條,也很久不會有反應。
可以使用wheel.passive來讓默認行為先觸發,不用等綁定的事件執行完畢后再觸發。
<div id="root"><ul @wheel.passive="getData"><li></li><li></li><li></li></ul></div>
但并不是所有的事件都在綁定事件執行完成后才執行,大部分事件會先執行默認行為(滾動事件中,scroll就是先執行默認事件,因此scroll不需要設置修飾符,也可以正常執行)。
鍵盤事件
兩個鍵盤事件
keydown 按下鍵盤就觸發,不需要抬起來。
keyup 按下鍵盤再抬起來才觸發。
鍵盤的名稱和編碼、如何設置按下特定按鍵時觸發綁定事件
input框內的數據通過event.target.value獲取。
設置按下特定按鍵時觸發綁定事件:語法是keyup.按鍵別名,表示按對應的按鍵時才觸發綁定事件。通過keyup/keydown.enter代表按下回車抬起時才觸發綁定的事件。
<body><input @keydown.enter="getKeyDown" id="root" v-model:="code"><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data(){return {code : '',}},methods:{getKeyDown(){console.log(`enter ${this.code}`);},}})</script>
</body>
(按center鍵觸發,輸出當前輸入框中的數據)
常見別名: enter 回車;delete 刪除/退格;esc 退出;space 空格;tab 換行;up 上;down 下;left 左;right 右
如果想要給某個按鍵綁定事件,但是這個事件不在vue提供的別名里,可以使用按鍵本身的名字來指定只有按下某個特殊的鍵時,才觸發綁定事件。鍵盤上每個按鍵都有自己的名字和編碼。event.key會返回按鍵的名字。event.keyCode可以獲得鍵盤事件按下的按鍵編碼。
<body><input @keydown="getKeyDown" id="root" v-model="code"><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data(){return {code : '',}},methods:{getKeyDown(){console.log(event.key);console.log(event.keyCode);},}})</script>
</body>
對于駝峰形式的key,不能直接寫key,應該把每個字母都變成小寫,并且用-連接。
以PageDown為例,如果想設置按下PageDown觸發事件:
<input @keydown.page-down="getKeyDown" id="root" v-model="code">
而且,不是鍵盤上所有的按鍵都可以綁定事件。
在某些瀏覽器上,通過keyup/keydown.按鍵編碼 也可以觸發綁定的事件,但是這種方式現在不被推薦,這種方式在漸漸被移除,在一些瀏覽器上無法生效(對于不同的設備,每個按鍵的編碼不完全一樣,所以這種方法在被移除)。
特殊的按鍵
tab鍵在常見按鍵里比較特殊,tab會把焦點從當前元素上切走。當前事件如果設定了keyup.tap,按鍵按下之后,焦點已經從當前元素上移走了,因此當keyup時,綁定的事件無法觸發(因為對于當前元素來說,當前元素已經不是之前的元素了,自然也沒有keyup事件)。因此tap使用在keydown上。
ctrl、alt、shift、meta(windows標志鍵)鍵也比較特殊。這些按鍵叫做系統修飾鍵。當這些按鍵配合keyup使用時,按下修飾鍵的同時,需要再按下其他鍵,當釋放其他按鍵時,keyup事件才會被觸發。當這些按鍵配合keydown使用時,不需要按下其他按鍵,只按按鍵本身就能觸發事件。
如果想設置鍵盤按下ctrl+y時才觸發,可以使用keyup.系統修飾鍵.另一個按鍵,用keyup.ctrl.y就可以實現這種效果。
vue自定義鍵盤名稱和編碼
Vue.config.keyCodes.自定義別名 = 按鍵編碼
比如Vue.config.keyCodes.myEnter = 13,可以定義一個叫myEnter的按鍵,他在按鍵編碼為13的鍵被按下或抬起時被識別。但這種方法也不太推薦。