自定義事件
自定義事件主要會被用于框架、組件設計與實現(xiàn)中。
自定義的事件有許多的創(chuàng)建方式,但實際的業(yè)務場景中幾乎不會被用到,網(wǎng)絡上的文獻記載其具體的使用場景也相對較少。
1. 使用 Event 構造函數(shù)
使用 Event
構造函數(shù)就可以創(chuàng)建一個自定義事件。
<style>
.btn { border: 1px solid #4caf50; padding: 8px 12px; min-width: 200px; color: #4caf50; background: white; outline: none; }
.btn:active { background: #4caf50; color: white; }
</style>
<div>
<button class="btn">點擊我</button>
</div>
<script>
var afterClick = new Event('afterclick');
var btnEle = document.querySelector('.btn');
btnEle.addEventListener('afterclick', function() {
alert('我是點擊事件執(zhí)行完后做的事情');
});
btnEle.onclick = function() {
alert('我被點擊了');
this.dispatchEvent(afterClick);
};
</script>
使用 new Event
可以創(chuàng)建一個自定義事件,事件名就是構造函數(shù)的第一個參數(shù) afterclick
,表示點擊事件完成后做的事情。
創(chuàng)建一個自定義事件后需要給 DOM 元素綁定這個事件,只有綁定后才能觸發(fā),使用 addEventListener
來綁定事件。
隨后再給按鈕綁定點擊事件,在事件末尾,即事情做完后,使用 dispatchEvent
觸發(fā)這個自定義事件。
自定義事件是需要手動觸發(fā)的!
Event
構造函數(shù)還支持第二個參數(shù),其接受一個對象,可以傳遞三個屬性,都為布爾值:
bubbles
默認 false ,表示是否會冒泡cancelable
默認 false , 表示事件是否可以被取消composed
默認 composed, 表示事件是否會在 Shadow DOM 根節(jié)點之外觸發(fā)。
2. 使用 CustomEvent 構造函數(shù)
上面使用 Event
構造函數(shù)的例子,將其替換成 CustomEvent
構造函數(shù)也是一樣可以執(zhí)行的。
<style>
.btn { border: 1px solid #4caf50; padding: 8px 12px; min-width: 200px; color: #4caf50; background: white; outline: none; }
.btn:active { background: #4caf50; color: white; }
</style>
<div>
<button class="btn">點擊我</button>
</div>
<script>
var afterClick = new CustomEvent('afterclick');
var btnEle = document.querySelector('.btn');
btnEle.addEventListener('afterclick', function() {
alert('我是點擊事件執(zhí)行完后做的事情,我被改成了 CustomEvent');
});
btnEle.onclick = function() {
alert('我被點擊了');
this.dispatchEvent(afterClick);
};
</script>
兩個例子效果是一樣的。
其主要的區(qū)別在參數(shù)和工作環(huán)境上,CustomEvent 是可以在 WebWorker 中被使用的,而 Event 不行。
CustomEvent 可以在構造函數(shù)的第二個參數(shù)中傳遞 detail
屬性,在事件觸發(fā)時,事件對象中就會攜帶這個 detail 屬性。
假設現(xiàn)在想完成一個鍵盤的點擊事件,即鍵盤上某個鍵按下并彈起后做的事情。
<style>
input {width: 200px;padding: 8px;font-size: 16px;outline: none;border: 1px dashed #4caf50;}
input:focus {border: 1px solid #4caf50;}
</style>
<div>
<input type="text">
</div>
<script>
var inputEle = document.querySelector('input');
var onKeyClick = function(e) {
console.log(e);
alert('現(xiàn)在輸入框內容是:' + e.detail.value + ',觸發(fā)的鍵是:' + e.detail.keyCode);
};
inputEle.addEventListener('keyup', (e) => {
console.log('鍵盤按鍵彈起了');
var keyClick = new CustomEvent('keyclick', {
detail: {
value: e.target.value,
keyCode: e.keyCode,
},
});
inputEle.addEventListener('keyclick', onKeyClick);
inputEle.dispatchEvent(keyClick);
inputEle.removeEventListener('keyclick', onKeyClick);
});
</script>
這里通過 keyup
事件,在事件處理器的最末尾增加了一個 keyclick
事件。這里并沒有結合 keydown
來判斷按鍵的落下和彈起,因為一個按鍵要彈起,必定得先落下,所以只需要監(jiān)聽 keyup
。
其實可以看出這段代碼比較奇怪,真正的業(yè)務場景并不會這樣寫,會選擇直接調用 onKeyClick
函數(shù)。
<style>
input {width: 200px;padding: 8px;font-size: 16px;outline: none;border: 1px dashed #4caf50;}
input:focus {border: 1px solid #4caf50;}
</style>
<div>
<input type="text">
</div>
<script>
var inputEle = document.querySelector('input');
var onKeyClick = function(value, keyCode) {
alert('現(xiàn)在輸入框內容是:' + value + ',觸發(fā)的鍵是:' + keyCode);
};
inputEle.addEventListener('keyup', (e) => {
console.log('鍵盤按鍵彈起了');
onKeyClick(e.target.value, e.keyCode);
});
</script>
這段代碼的執(zhí)行結果和采用 CustomEvent
的效果是一樣的。
這就是為什么自定義事件更常用于框架或者庫,因為暴露事件有時候比單純的提供回調配置項更好理解和解耦。
3. document.createEvent
使用 document.createEvent 也可以用來創(chuàng)建自定義事件,但其由于許多配套屬性、方法都已經(jīng)從標準中移除,MDN 也不再建議開發(fā)者使用,所以這里不再深入探討,只做了解。
4. 小結
自定義事件不常用,主要被應用于框架級別的設計上,日常開發(fā)很少有使用場景,許多場景下還會讓代碼變得冗余復雜。