JS DOM Event
- 采用事件驅(qū)動(dòng)模式,任務(wù)的執(zhí)行不取決代碼的順序啸箫,而取決于某一個(gè)事件是否發(fā)生忘苛。
1. 事件冒泡Bubbling
1.1 Bubbling
When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.
The process is called “bubbling”, because events “bubble” from the inner element up through parents like a bubble in the water.
就是如果事件發(fā)生在內(nèi)部子元素上扎唾,這個(gè)事件也會(huì)觸發(fā)父元素的該事件處理器。比如父元素有onclick = "myFunction()"扮宠,你沒按父元素但按了里面的子元素狐榔,父元素的myFunction()會(huì)被觸發(fā)運(yùn)行薄腻。這個(gè)被按的子元素是這個(gè)event的target,用event.target
可以找到
function changeBgColor() {
if (event.target.style.backgroundColor === "pink") {
event.target.style.backgroundColor = "yellow";
} else {
event.target.style.backgroundColor = "pink";
}
}
1.2 Stop Bubbling
If we don't want the parent element handler to be triggered by child element, you can stop bubbling. ONLY stop bubbling if you really need it, otherwise bubbling is convenient.
不想讓子元素的事件冒泡上來罢艾,在該子元素上用method event.stopPropagation()
<div onclick = "myFunction()">
<p onclick = "event.stopPropagation()">
paragrah text.
</p>
</div>
2. 事件捕獲Capture
如果說bubbling是從下往上咐蚯,那么capture就是從上往下春锋,從外層父元素一直到target所在的元素差凹。通常用on<event>這種格式,或者用addEventListener設(shè)置的handler呐萌,不執(zhí)行capture谊娇,只執(zhí)行bubbling邮绿。如果要讓他們執(zhí)行capture,要設(shè)置{capture: true}顾腊。
<body>
<div>
<p id="p1">
<input type="button" id="captureDemo" />
</p>
</div>
<script>
var demo = document.getElementById("captureDemo");
var p1 = document.getElementById("p1");
demo.addEventListener("click", e => alert("Capturing demo"), true);
p1.addEventListener("click", e => alert("Capturing p1"), true);
</script>
</body>
上述例子中杂靶,由于p1和captureDemo都設(shè)置了capture:true,所以點(diǎn)button的時(shí)候吗垮,會(huì)先顯示"Capturing p1", 再顯示"Capturing demo"烁登,從外到內(nèi)。
3. 事件委托Event Delegation
翻譯成中文叫事件委托或者事件代理锨络。因?yàn)閑vent handler過多會(huì)影響頁面性能狼牺,把一些子元素的event handler統(tǒng)一放到他們的共同爸爸那里,減少handler數(shù)量掠归,能更快訪問虏冻。
The idea is that if we have a lot of elements handled in a similar way, then instead of assigning a handler to each of them – we put a single handler on their common ancestor.
In the handler we get event.target
, see where the event actually happened and handle it.
4.事件監(jiān)聽后觸發(fā)函數(shù)的參數(shù)傳遞
When an event happens, your assigned function will be invoked, and the "event" will be the default first parameter of the function. 用addEventListener時(shí)兄旬,event是默認(rèn)形參余寥,就跟array.reduce(function(prev, curr) {})里面默認(rèn)傳prev悯森,curr一樣。
element.addEventListener("click", myFunction);
function myFunction() {};
element.addEventListener("click", function () {}); //里面第二個(gè)參數(shù)可以是直接的函數(shù)表達(dá)式或者一個(gè)函數(shù)名字祝蝠,函數(shù)內(nèi)容在外部定義
element.onclick = "myFunction()"绎狭; //這里加引號(hào)褥傍,里面直接調(diào)用函數(shù)運(yùn)行所以函數(shù)后面加括號(hào)
對(duì)于event則放在函數(shù)定義里面作為形參(符號(hào)無所謂),具體哪個(gè)event會(huì)作為實(shí)參傳進(jìn)來:
document.getElementById("myBtn").addEventListener("click", myFunction);
function myFunction(event) {
document.getElementById("demo").innerHTML = "Hello World";
alert(event.target); //這里event作為形參的話其實(shí)符號(hào)無所謂蹦狂,比如可以寫成function myFunction(e){alert(e.target);}, 反正到時(shí)候具體那個(gè)event會(huì)作為這個(gè)e被傳進(jìn)來
function myFunction() {
document.getElementById("demo").innerHTML = "Hello World";
alert(event.target); //這樣也work,因?yàn)閑vent直接綁定了窜骄,這里的event是固定符號(hào)。但最好還是寫上event傳遞邻遏,便于代碼閱讀
對(duì)于onclick = "functionName()"中党远,event也是默認(rèn)綁定富弦,可以不用傳。如果要傳遞济似,在onclick那句語句中以實(shí)參傳遞盏缤,函數(shù)定義的時(shí)候?qū)懮闲螀ⅰ?/p>
<button onclick="displayDate()">The time is?</button>
<script>
function displayDate() {
document.getElementById("demo").innerHTML = Date();
alert(event.target);
}
</script>
<button onclick="displayDate(event)">The time is?</button>
<script>
function displayDate(e) {
document.getElementById("demo").innerHTML = Date();
alert(e.target);
}
</script>