Vue.js-03:第三章
一、前言
熟悉了 Vue 的指令系統後,在實際開發中,不可避免的會使用到對於事件的操作,如何處理 DOM 事件流,成為我們必須要掌握的技能。不同於傳統的前端開發,在 Vue 中給我們提供了事件修飾符這一利器,使我們可以便捷的處理 DOM 事件,本章,一起來學習如何使用事件修飾符來實現對於 DOM 事件流的操作。
二、乾貨合集
1、 DOM 事件流
有時,當我們需要完成頁面中的某些功能時,我們要在需要實現功能的頁面元素上使用 v-on 指令去監聽 DOM 事件,在 html4 時代瀏覽器如何確定頁面的哪一部分會擁有特定的事件時,IE 和 Netscape 的開發團隊提出了兩個截然相反的概念。這一差異,也使我們在寫程式碼中需要考慮如何去處理 DOM 的事件細節。為了解決這一問題,vue 給我們提供了事件修飾符這一利器,它使我們的方法只有純粹的資料邏輯,而不是去處理 DOM 事件細節。
一些涉及到概念:
a)事件:使用者設定或者是瀏覽器自身執行的某種動作。例如click(點選)、load(載入)、mouseover(滑鼠懸停)、change(改變)等等
b)事件處理程式:為了實現某個事件的功能而構建的函式方法,也可稱為事件監聽器
c)DOM 事件流:描述的是從頁面中接收事件的順序,也可理解為事件在頁面中傳播的順序
在 DOM 事件流中存在著三個階段:事件捕獲階段、處於目標階段、事件冒泡階段。
a)事件捕獲(event capture):當滑鼠點選或者觸發 DOM 事件時,瀏覽器會從根節點開始由外到內進行事件傳播,即點選了子元素,如果父元素通過事件捕獲方式註冊了對應的事件的話,會先觸發父元素繫結的事件
b)事件冒泡(event bubbing):當滑鼠點選或者觸發 DOM 事件時,瀏覽器會從根節點開始由內到外進行事件傳播,即點選了子元素,則先觸發子元素繫結的事件,逐步擴散到父元素繫結的事件
之前我們提到的 IE 和 Netscape 的開發團隊提出了兩個截然相反的事件流概念,IE 採取的是事件冒泡流,而標準的瀏覽器的事件流則是事件捕獲流。所以,為了相容 IE 我們需要改變某些的寫法。
2、 事件修飾符
a).stop:阻止事件冒泡 在下面的示例中,我們分別建立了一個 button 的點選事件和外側的 div 的點選事件,根據事件的冒泡機制我們可以得知,當我們點選了按鈕之後,會擴散到父元素,從而觸發父元素的點選事件,具體的結果也如下圖所示:
1 <div id="app" class="divDefault"> 2 <div id="div1" @click="divHandlerClick"> 3 <input type="button" value="點選" @click="btnHandlerClick" /> 4 </div> 5 </div> 6 7 <script> 8 var vm = new Vue({ 9 el: '#app', 10 data: {}, 11 methods: { 12 divHandlerClick() { 13 alert('我是div的點選事件!') 14 }, 15 btnHandlerClick() { 16 alert('我是button的點選事件') 17 } 18 } 19 }); 20 </script>
這時候,如果我們不希望出現事件冒泡,則可以使用 Vue 內建的修飾符便捷的阻止事件冒泡的產生。因為我們是點選 button 後產生的事件冒泡,我們只需要在 button 的點選事件上加上 stop 修飾符即可,示例程式碼如下。
<input type="button" value="點選" @click.stop="btnHandlerClick" />
b).prevent:阻止預設事件
阻止預設事件這個也很好理解,有些標籤本身會存在事件,例如,a 標籤的跳轉,form 表單中 submit 按鈕的提交事件等等,在某些時候我們只想執行我們自己設定的事件,這時,就需要阻止標籤的預設事件的執行,原生的 js 我們可以使用 preventDefault 方法來實現,而在 Vue 中,我們只需要使用 prevent 關鍵字就可以了。
在下面的示例中,我們為 a 標籤添加了一個點選事件,由於 a 標籤本身具有預設的跳轉事件,此時,當我們點選後,最終還是會執行 a 標籤的預設事件。
1 <a href="http://www.baidu.com" @click="aHandlerClick">連結跳轉</a> 2 3 <script> 4 var vm = new Vue({ 5 el: '#app', 6 data: {}, 7 methods: { 8 aHandlerClick() { 9 alert('我是a標籤的點選事件') 10 } 11 } 12 }); 13 </script>
在 Vue 中,當我們想要阻止元素的預設事件,只需要在繫結的事件後使用 prevent 修飾符即可,示例程式碼如下。
<a href="http://www.baidu.com" @click.prevent="aHandlerClick">連結跳轉</a>
c).capture:新增事件監聽器時使用事件捕獲模式 在上面的學習中我們瞭解到,事件捕獲模式與事件冒泡模式是一對相反的事件處理流程,當我們想要將頁面元素的事件流改為事件捕獲模式時,只需要在父級元素的事件上使用 capture 修飾符即可,還是上面的例子的程式碼,當我們在 div 繫結的點選事件上使用 capture 修飾符後,我們點選按鈕首先觸發的就是最外側的 div 的事件。
1 <div id="app" class="divDefault"> 2 <div id="div1" @click.capure="divHandlerClick"> 3 <input type="button" value="點選" @click="btnHandlerClick" /> 4 </div> 5 </div>
d).self:只當在 event.target 是當前元素自身時觸發處理函式(比如不是子元素冒泡引起的事件觸發) 在上面的例子中,我們為 div 綁定了一個點選事件,而我們的本意可能是隻有當我們點選 div 後觸發這個事件,而實際情況是事件冒泡還是事件捕獲都會觸發這個事件,這與我們的本意是不符的。在 Vue 中,我們就可以使用 self 修飾符去修飾事件,讓這個事件只在我們想要觸發時觸發。
<div id="app" class="divDefault"> <div id="div1" @click.self="divHandlerClick"> <input type="button" value="點選" @click="btnHandlerClick" /> </div> </div>
e).once:事件只觸發一次 當我們僅僅想對繫結的事件只在第一次的時候觸發,這時我們就可以使用 once 修飾符去修飾繫結的事件。例如在下面的程式碼中,只有第一次點選時才會觸發繫結的事件,之後點選都不會觸發。
<input type="button" value="點選" @click.once="btnHandlerClick" />
f).passive:滾動事件的預設行為 (即滾動行為) 將會立即觸發 在頁面滾動的時候,瀏覽器會在整個事件處理完畢之後再觸發滾動,因為瀏覽器並不知道這個事件是否在其處理函式中被呼叫了 event.preventDefault(),而 passive 修飾符用來進一步告訴瀏覽器這個事件的預設行為不會被取消,即 使用 passive 修飾符後表示繫結的事件永遠不會呼叫 event.preventDefault()。
三、總結
1、事件修飾符的使用順序很重要
使用修飾符時,順序很重要;相應的程式碼會以同樣的順序產生。因此,用 v-on:click.prevent.self 會阻止所有的點選,而 v-on:click.self.prevent 只會阻止對元素自身的點選。
2、.passive 和 .prevent不能一起使用
不要把 .passive 和 .prevent 一起使用,因為 .prevent 將會被忽略,同時瀏覽器可能會向你展示一個警告。請記住,.passive 會告訴瀏覽器你不想阻止事件的預設行為。