在Vue進行前端開發中,事件監聽是必不可少的功能,本文通過簡單的小例子,簡述v-on的簡單用法,僅供學習分享使用,如有不足之處,還請指正。 ...
在Vue進行前端開發中,事件監聽是必不可少的功能,本文通過簡單的小例子,簡述v-on的簡單用法,僅供學習分享使用,如有不足之處,還請指正。
監聽事件
可以用 v-on 指令監聽 DOM 事件,併在觸發時運行一些 JavaScript 代碼。如下所示:
1 <button v-on:click="counter += 1">Add 1</button> 2 <p>按鈕被點擊了 {{ counter }} 次.</p>
其中counter為Vue自定義的一個屬性值。
事件處理方法
事實上,許多事件處理邏輯會更為複雜,所以直接把 JavaScript 代碼寫在 v-on 指令中是不可行的。因此 v-on 還可以接收一個需要調用的方法名稱。如下所示:
1 <button v-on:click="greet">Greet</button>
greet 是在下麵定義的方法名。如下所示:
1 <script type="text/javascript"> 2 var app=new Vue({ 3 el:'#app', 4 data:{ 5 msg:'hello world!!!', 6 counter:0, 7 name: 'Vue.js' 8 }, 9 // 在 `methods` 對象中定義方法 10 methods:{ 11 greet: function (event) { 12 // `this` 在方法里指向當前 Vue 實例 13 alert('Hello ' + this.name + '!') 14 // `event` 是原生 DOM 事件 15 if (event) { 16 alert(event.target.tagName) 17 } 18 }, 19 20 } 21 }); 22 </script>
內聯處理器中的方法
除了直接綁定到一個方法,也可以在內聯 JavaScript 語句中調用方法,如下所示:
1 <button v-on:click="say('hi')">Say hi</button> 2 <button v-on:click="say('what')">Say what</button>
有時也需要在內聯語句處理器中訪問原始的 DOM 事件。可以用特殊變數 $event 把它傳入方法:
1 <button v-on:click="warn('表單不能被提交.', $event)">提交</button>
其中say,warn均為自定義方法,如下所示:
1 say: function (message) { 2 alert(message); 3 }, 4 warn: function (message, event) { 5 // 現在我們可以訪問原生事件對象 6 if (event) { 7 event.preventDefault(); 8 } 9 alert(message); 10 }
事件修飾符
在事件處理程式中調用 event.preventDefault() 或 event.stopPropagation() 是非常常見的需求。儘管我們可以在方法中輕鬆實現這點,但更好的方式是:方法只有純粹的數據邏輯,而不是去處理 DOM 事件細節。為瞭解決這個問題,Vue.js 為 v-on 提供了事件修飾符。之前提過,修飾符是由點開頭的指令尾碼來表示的。事件修飾符共以下幾種:
- .stop
- .prevent
- .capture
- .self
- .once
- .passive
1 <!-- 阻止單擊事件繼續傳播 --> 2 <a v-on:click.stop="doThis">點擊666</a> 3 <!-- 提交事件不再重載頁面 --> 4 <form v-on:submit.prevent="onSubmit"> 5 <div>阻止提交</div> 6 </form> 7 <!-- 修飾符可以串聯 --> 8 <a v-on:click.stop.prevent="doThat"></a> 9 <!-- 只有修飾符 --> 10 <form v-on:submit.prevent> 11 <div id="d">只有修飾符</div> 12 </form> 13 <!-- 添加事件監聽器時使用事件捕獲模式 --> 14 <!-- 即內部元素觸發的事件先在此處理,然後才交由內部元素進行處理 --> 15 <div v-on:click.capture="doThis">doThis...</div> 16 <!-- 只當在 event.target 是當前元素自身時觸發處理函數 --> 17 <!-- 即事件不是從內部元素觸發的 --> 18 <div v-on:click.self="doThat">doThat...</div>View Code
使用修飾符時,順序很重要;相應的代碼會以同樣的順序產生。因此,用 v-on:click.prevent.self 會阻止所有的點擊,而 v-on:click.self.prevent 只會阻止對元素自身的點擊。
新增屬性
不像其它只能對原生的 DOM 事件起作用的修飾符,.once 修飾符還能被用到自定義的組件事件上。
1 <!-- 點擊事件將只會觸發一次 --> 2 <a v-on:click.once="doThis">點我一次666</a>
Vue 還對應 addEventListener 中的 passive 選項提供了 .passive 修飾符。
1 <!-- 滾動事件的預設行為 (即滾動行為) 將會立即觸發 --> 2 <!-- 而不會等待 `onScroll` 完成 --> 3 <!-- 這其中包含 `event.preventDefault()` 的情況 --> 4 <div v-on:scroll.passive="onScroll">...</div>
這個 .passive 修飾符尤其能夠提升移動端的性能。不要把 .passive 和 .prevent 一起使用,因為 .prevent 將會被忽略,同時瀏覽器可能會向你展示一個警告。請記住,.passive 會告訴瀏覽器你不想阻止事件的預設行為。
按鍵修飾符
在監聽鍵盤事件時,我們經常需要檢查詳細的按鍵。Vue 允許為 v-on 在監聽鍵盤事件時添加按鍵修飾符:
1 <!-- 只有在 `key` 是 `Enter` 時調用 `vm.submit()` ,點擊時不調用 --> 2 <input v-on:keyup.enter="submit" type="text" value="點我777" /> 3 <!-- 可以直接將 KeyboardEvent.key 暴露的任意有效按鍵名轉換為 kebab-case 來作為修飾符。--> 4 <input v-on:keyup.page-down="onPageDown" type="text" value="點我888" /> 5 <!-- 在上述示例中,處理函數只會在 $event.key 等於 PageDown 時被調用。且游標在時才管用。 -->
系統修飾符
可以用如下修飾符來實現僅在按下相應按鍵時才觸發滑鼠或鍵盤事件的監聽器。
- .ctrl
- .alt
- .shift
- .meta
註意:在 Mac 系統鍵盤上,meta 對應 command 鍵 (⌘)。在 Windows 系統鍵盤 meta 對應 Windows 徽標鍵 (⊞)。在 Sun 操作系統鍵盤上,meta 對應實心寶石鍵 (◆)。在其他特定鍵盤上,尤其在 MIT 和 Lisp 機器的鍵盤、以及其後繼產品,比如 Knight 鍵盤、space-cadet 鍵盤,meta 被標記為“META”。在 Symbolics 鍵盤上,meta 被標記為“META”或者“Meta”。
1 <!-- Alt + C --> 2 <input @keyup.alt.67="clear"> 3 4 <!-- Ctrl + Click --> 5 <div @click.ctrl="doSomething">Do something</div>
請註意:修飾鍵與常規按鍵不同,在和 keyup 事件一起用時,事件觸發時修飾鍵必須處於按下狀態。換句話說,只有在按住 ctrl 的情況下釋放其它按鍵,才能觸發 keyup.ctrl。而單單釋放 ctrl 也不會觸發事件。如果你想要這樣的行為,請為 ctrl 換用 keyCode:keyup.17。
.exact 修飾符
.exact 修飾符允許你控制由精確的系統修飾符組合觸發的事件。
1 <!-- 即使 Alt 或 Shift 被一同按下時也會觸發 --> 2 <button @click.ctrl="onClick">A</button> 3 <!-- 有且只有 Ctrl 被按下的時候才觸發 --> 4 <button @click.ctrl.exact="onCtrlClick">A</button> 5 <!-- 沒有任何系統修飾符被按下的時候才觸發 --> 6 <button @click.exact="onClick">A</button>
滑鼠按鈕修飾符
這些修飾符會限制處理函數僅響應特定的滑鼠按鈕,如下所示:
- .left
- .right
- .middle
為什麼在 HTML 中監聽事件?
你可能註意到這種事件監聽的方式違背了關註點分離 (separation of concern) 這個長期以來的優良傳統。但不必擔心,因為所有的 Vue.js 事件處理方法和表達式都嚴格綁定在當前視圖的 ViewModel 上,它不會導致任何維護上的困難。實際上,使用 v-on 有幾個好處:
- 掃一眼 HTML 模板便能輕鬆定位在 JavaScript 代碼里對應的方法。
- 因為你無須在 JavaScript 里手動綁定事件,你的 ViewModel 代碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易於測試。
- 當一個 ViewModel 被銷毀時,所有的事件處理器都會自動被刪除。你無須擔心如何清理它們。
本例中全部代碼如下所示:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>事件處理</title> 6 <!-- 開發環境版本,包含了有幫助的命令行警告 --> 7 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 8 </head> 9 <body> 10 <div id="app"> 11 <h2>監聽事件</h2> 12 <!-- 13 可以用 v-on 指令監聽 DOM 事件,併在觸發時運行一些 JavaScript 代碼。 14 --> 15 <button v-on:click="counter += 1">Add 1</button> 16 <p>按鈕被點擊了 {{ counter }} 次.</p> 17 <h2>事件處理方法</h2> 18 <!-- 19 然而許多事件處理邏輯會更為複雜,所以直接把 JavaScript 代碼寫在 v-on 指令中是不可行的。 20 因此 v-on 還可以接收一個需要調用的方法名稱。 21 --> 22 <!-- `greet` 是在下麵定義的方法名 --> 23 <button v-on:click="greet">Greet</button> 24 <!-- 25 // 也可以用 JavaScript 直接調用方法 26 //app.greet() // => 'Hello Vue.js!' 27 --> 28 <h2>內聯處理器中的方法</h2> 29 <!-- 30 除了直接綁定到一個方法,也可以在內聯 JavaScript 語句中調用方法: 31 --> 32 <button v-on:click="say('hi')">Say hi</button> 33 <button v-on:click="say('what')">Say what</button> 34 <!-- 35 有時也需要在內聯語句處理器中訪問原始的 DOM 事件。可以用特殊變數 $event 把它傳入方法: 36 --> 37 <br> 38 <button v-on:click="warn('表單不能被提交.', $event)">提交</button> 39 <h2>事件修飾符</h2> 40 <!-- 41 在事件處理程式中調用 event.preventDefault() 或 event.stopPropagation() 是非常常見的需求。 42 儘管我們可以在方法中輕鬆實現這點,但更好的方式是:方法只有純粹的數據邏輯,而不是去處理 DOM 事件細節。 43 為瞭解決這個問題,Vue.js 為 v-on 提供了事件修飾符。之前提過,修飾符是由點開頭的指令尾碼來表示的。 44 .stop 45 •.prevent 46 •.capture 47 •.self 48 •.once 49 •.passive 50 --> 51 <!-- 阻止單擊事件繼續傳播 --> 52 <a v-on:click.stop="doThis">點擊666</a> 53 <br> 54 <!-- 提交事件不再重載頁面 --> 55 <form v-on:submit.prevent="onSubmit"> 56 <div> 57 阻止提交 58 </div> 59 </form> 60 <br> 61 <!-- 修飾符可以串聯 --> 62 <a v-on:click.stop.prevent="doThat"></a> 63 <br> 64 <!-- 只有修飾符 --> 65 <form v-on:submit.prevent> 66 <div id="d"> 67 只有修飾符 68 </div> 69 </form> 70 <br> 71 <!-- 添加事件監聽器時使用事件捕獲模式 --> 72 <!-- 即內部元素觸發的事件先在此處理,然後才交由內部元素進行處理 --> 73 <div v-on:click.capture="doThis">doThis...</div> 74 <br> 75 <!-- 只當在 event.target 是當前元素自身時觸發處理函數 --> 76 <!-- 即事件不是從內部元素觸發的 --> 77 <div v-on:click.self="doThat">doThat...</div> 78 <!-- 79 使用修飾符時,順序很重要;相應的代碼會以同樣的順序產生。 80 因此,用 v-on:click.prevent.self 會阻止所有的點擊,而 v-on:click.self.prevent 只會阻止對元素自身的點擊。 81 --> 82 <h2>新增</h2> 83 <!-- 點擊事件將只會觸發一次 --> 84 <a v-on:click.once="doThis">點我一次666</a> 85 <!-- 86 不像其它只能對原生的 DOM 事件起作用的修飾符,.once 修飾符還能被用到自定義的組件事件上。 87 --> 88 <!-- 89 Vue 還對應 addEventListener 中的 passive 選項提供了 .passive 修飾符。 90 --> 91 <!-- 滾動事件的預設行為 (即滾動行為) 將會立即觸發 --> 92 <!-- 而不會等待 `onScroll` 完成 --> 93 <!-- 這其中包含 `event.preventDefault()` 的情況 --> 94 <div v-on:scroll.passive="onScroll">...</div> 95 <!-- 96 這個 .passive 修飾符尤其能夠提升移動端的性能。 97 !不要把 .passive 和 .prevent 一起使用,因為 .prevent 將會被忽略,同時瀏覽器可能會向你展示一個警告。 98 請記住,.passive 會告訴瀏覽器你不想阻止事件的預設行為。 99 --> 100 <h2>按鍵修飾符</h2> 101 <!-- 102 在監聽鍵盤事件時,我們經常需要檢查詳細的按鍵。Vue 允許為 v-on 在監聽鍵盤事件時添加按鍵修飾符: 103 --> 104 <!-- 只有在 `key` 是 `Enter` 時調用 `vm.submit()` ,點擊時不調用 --> 105 <input v-on:keyup.enter="submit" type="text" value="點我777" /> 106 <!-- 107 可以直接將 KeyboardEvent.key 暴露的任意有效按鍵名轉換為 kebab-case 來作為修飾符。 108 --> 109 <input v-on:keyup.page-down="onPageDown" type="text" value="點我888" /> 110 <!-- 111 在上述示例中,處理函數只會在 $event.key 等於 PageDown 時被調用。且游標在時才管用。 112 --> 113 <h2>#按鍵碼</h2> 114 <!-- 115 keyCode 的事件用法已經被廢棄了並可能不會被最新的瀏覽器支持。 使用 keyCode attribute 也是允許的: 116 --> 117 <input v-on:keyup.13="submit" type="button" value="key up 13"> 118 <!-- 119 為了在必要的情況下支持舊瀏覽器,Vue 提供了絕大多數常用的按鍵碼的別名: 120 .enter 121 •.tab 122 •.delete (捕獲“刪除”和“退格”鍵) 123 •.esc 124 •.space 125 •.up 126 •.down 127 •.left 128 •.right 129 !有一些按鍵 (.esc 以及所有的方向鍵) 在 IE9 中有不同的 key 值, 如果你想支持 IE9,這些內置的別名應該是首選。 130 你還可以通過全局 config.keyCodes 對象自定義按鍵修飾符別名: 131 // 可以使用 `v-on:keyup.f1` 132 Vue.config.keyCodes.f1 = 112 133 --> 134 <h2>系統修飾鍵</h2> 135 <!-- 136 可以用如下修飾符來實現僅在按下相應按鍵時才觸發滑鼠或鍵盤事件的監聽器。 137 .ctrl 138 •.alt 139 •.shift 140 •.meta 141 註意:在 Mac 系統鍵盤上,meta 對應 command 鍵 (⌘)。 142 在 Windows 系統鍵盤 meta 對應 Windows 徽標鍵 (⊞)。在 Sun 操作系統鍵盤上,meta 對應實心寶石鍵 (◆)。 143 在其他特定鍵盤上,尤其在 MIT 和 Lisp 機器的鍵盤、以及其後繼產品,比如 Knight 鍵盤、space-cadet 鍵盤,meta 被標記為“META”。 144 在 Symbolics 鍵盤上,meta 被標記為“META”或者“Meta”。 145 --> 146 <!-- Alt + C --> 147 <input @keyup.alt.67="clear"> 148 149 <!-- Ctrl + Click --> 150 <div @click.ctrl="doSomething">Do something</div> 151 <!-- 152 !請註意修飾鍵與常規按鍵不同,在和 keyup 事件一起用時,事件觸發時修飾鍵必須處於按下狀態。 153 換句話說,只有在按住 ctrl 的情況下釋放其它按鍵,才能觸發 keyup.ctrl。而單單釋放 ctrl 也不會觸發事件。 154 如果你想要這樣的行為,請為 ctrl 換用 keyCode:keyup.17。 155 --> 156 <h2>#.exact 修飾符</h2> 157 <!-- 158 .exact 修飾符允許你控制由精確的系統修飾符組合觸發的事件。 159 --> 160 <!-- 即使 Alt 或 Shift 被一同按下時也會觸發 --> 161 <button @click.ctrl="onClick">A</button> 162 163 <!-- 有且只有 Ctrl 被按下的時候才觸發 --> 164 <button @click.ctrl.exact="onCtrlClick">A</button> 165 166 <!-- 沒有任何系統修飾符被按下的時候才觸發 --> 167 <button @click.exact="onClick">A</button> 168 <h2>#滑鼠按鈕修飾符</h2> 169 <!-- 170 .left 171 •.right 172 •.middle 173 174 這些修飾符會限制處理函數僅響應特定的滑鼠按鈕。 175 176 --> 177 <h2>為什麼在 HTML 中監聽事件?</h2> 178 <!-- 179 你可能註意到這種事件監聽的方式違背了關註點分離 (separation of concern) 這個長期以來的優良傳統。 180 但不必擔心,因為所有的 Vue.js 事件處理方法和表達式都嚴格綁定在當前視圖的 ViewModel 上,它不會導致任何維護上的困難。 181 實際上,使用 v-on 有幾個好處: 182 1.掃一眼 HTML 模板便能輕鬆定位在 JavaScript 代碼里對應的方法。 183 2.因為你無須在 JavaScript 里手動綁定事件,你的 ViewModel 代碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易於測試。 184 3.當一個 ViewModel 被銷毀時,所有的事件處理器都會自動被刪除。你無須擔心如何清理它們。 185 --> 186 </div> 187 <script type="text/javascript"> 188 var app=new Vue({ 189 el:'#app', 190 data:{ 191 msg:'hello world!!!', 192 counter:0, 193 name: 'Vue.js' 194 }, 195 // 在 `methods` 對象中定義方法 196 methods:{ 197 greet: function (event) { 198 // `this` 在方法里指向當前 Vue 實例 199 alert('Hello '