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