瀏覽器默認行為(browser default actions)
上一期談到了瀏覽器事件委托:給外層元素綁定一個listener,可以處理子元素上觸發的瀏覽器默認行為。事件委托可以大量減少js的DOM綁定,從而提升頁面性能。
這一期通過現實中的幾個案例進一步拓展一下瀏覽器actions。
案例1: 阻止url跳轉
阻止瀏覽器的默認行為主要是兩種方式:
在事件捕獲、冒泡階段對元素或其父級元素調用
event.preventDefault()
對元素或其父級元素加
on<event>
(如onclick),并return false
(注:addEventListener無效)
對<a href="#">
阻止默認action后,點擊該標簽后將不會觸發url跳轉:
<a href="#" onclick="return false">return false</a>
<a href="#" onclick="event.preventDefault()">event.preventDefault()</a>
<div onclick="return false">
<a href="#">parent prevent way1</a>
</div>
<div onclick="event.preventDefault()">
<a href="#">parent prevent way2</a>
</div>
案例2:<input type="radio">
前段時間在寫vue的時候發現一個有趣的問題,如圖:
選擇場地,有且只能選一個。點select按鈕后,Schedule會更新時間和地點。
我看了一下組里小朋友的實現,大體思路是:
- 每個按鈕綁定一個listener,點擊后把該按鈕的value保存到state里;
- 接著state更新Schedule里的信息;
- 再遍歷其他行里的selected按鈕并改成unselected。
很復雜很復雜,性能也堪憂。
仔細觀察原型后可以發現每個select按鈕都是互斥的,這就是一個典型的radio事件。
我簡單實現了一個demo,通過事件委托拿到radio的actions:
<h2>Checked item: {{radio}}</h2>
<ul @click="radioFn">
<li v-for="(item, idx) in items" :key="idx">
<span>{{item}}</span>
<label>
<input type="radio" name="radio" :value="item"/>
<div class="btn btn-primary selected">selected</div>
<div class="btn btn-light unselected">unselected</div>
</label>
</li>
</ul>
radioFn
在冒泡階段拿到來自子級元素的INPUT
事件后,就可以獲得被checked的radio的value了。相應地,其他radio會被瀏覽器自動置為unchecked。
radioFn (e) {
let target = e.target
if ('INPUT' === target.nodeName)
this.radio = target.value
}
CSS有點trick,用到了偽類和兄弟選擇器。有空我再深入介紹一下,這里暫且不談。
input[type="radio"] {
position: absolute;
left: 10em;
display: none;
}
input[type="radio"]:checked ~ .unselected {
display: none;
}
input[type="radio"]:not(checked) ~ .selected {
display: none;
}
input[type="radio"]:not(checked) ~ .unselected {
display: block;
}
input[type="radio"]:checked ~ .selected {
display: block;
}
至此,只需要在父級元素里綁定一個listener就可以實現上述案例的所有功能了。即便之后把radio所在行包在某component里面,上述實現依舊有效。
擴展:<input type="checkbox">
有了radio的hint,出一道quiz。如圖所示,問如何獲取到所有已點選的checkbox信息?
其他
接著再列舉一些無趣也不知道是否有用的的小知識:
-
我們可以用
return false
使鼠標focus
輸入框時無效,但是還是可以通過其他途徑到達輸入框, 如按Tab
,或是按input
關聯的label
。例:<input value="focus works" onfocus="this.value=''"/> <input value="disable mouse down" onmousedown="return false"/>
-
可以disable掉鼠標右鍵瀏覽器下拉菜單,也可以定制自己的事件。
<button oncontextmenu="return false"> 鼠標右鍵后將不會出現默認的瀏覽器下拉菜單 </button>
-
當
input
的type為submit或是reset時,它就變成了button。-
type="submit"
會觸發form的method -
type="reset"
能將form里的域置為初始值
<form action="#" method="get"> <label for="firstname">First Name:</label> <input id="firstname" name="firstname" /><br> <label for="lastname">Last Name:</label> <input id="lastname" name="lastname" /><br> <input type="submit"/> <input type="reset"/> </form>
-
小結
瀏覽器提供了很多默認的actions,下面列了一些常用到的事件:
- mousedown: 鼠標左鍵點擊控件
-
checkbox、radio:
<input>
返回checked和unchecked信息 -
submit、reset: 提交、重置
<form>
里的信息,并且綁定了回車熱鍵 - wheel: 鼠標滾輪操作
- keydown:在輸入框內輸入信息
- contextmenu: 鼠標右鍵展示下拉菜單
靈活使用這些默認的actions,可以幫助我們省去大量的js操作,提高網頁性能。當不需要時,使用event.preventDefault()
或是return false
就可以阻止它們了。