DOM Event 天生具有 Event Propagation 特性,且是由內向外觸發 Event,若想由外向內觸發,則稱為 Event Capturing,Vue 提供了 capture
Event Modifier,讓我們在 HTML Template 就能以 Declarative 形式使 Event 往內層傳遞。
Version
Vue 2.6.11
Tailwind CSS 1.8.10
Event Propagation
按下 Click Me
,會發現 內
、中
、外
3 個 click
event 都會被觸發,這正是其 Event Propagation 特性。
當按下綠色部分,會發現只有 中
與 外
2 個 click
event 都會被觸發,內
則不觸發,因為 Event Propagation 只會向外,而不會向內。
<template>
<div @click="onOuterClick" class="p-3 bg-blue-500">
<div @click="onMiddleClick" class="p-3 bg-green-500">
<div @click="onInnerClick" class="bg-red-500">Click Me</div>
</div>
</div>
</template>
<script>
let onOuterClick = function() {
console.log('Outer click')
}
let onMiddleClick = function() {
console.log('Middle click')
}
let onInnerClick = function() {
console.log('Inner click')
}
export default {
methods: {
onOuterClick,
onMiddleClick,
onInnerClick
}
}
</script>
第 2 行
<div @click="onOuterClick" class="p-3 bg-blue-500">
<div @click="onMiddleClick" class="p-3 bg-green-500">
<div @click="onInnerClick" class="bg-red-500">Click Me</div>
</div>
</div>
三層 <div>
的 click
event 都有其 event handler,因此能觀察 Event Propagation,且每個 <div>
都增加其 padding 方便 click。
element.addEventListener()
按下 Click Me
,會發現 內
、中
、外
3 個 click
event 都會被觸發,但順序與 Event Propagation 相反,而是由外向內觸發,此稱為 Event Capturing。
當按下綠色部分,會發現只有 中
與 外
2 個 click
event 都會被觸發,內
則不觸發,但順序與 Event Propagation 相反,而是由外向內觸發。
<template>
<div ref="outer" class="p-3 bg-blue-500">
<div ref="middle" class="p-3 bg-green-500">
<div ref="inner" class="bg-red-500">Click Me</div>
</div>
</div>
</template>
<script>
let onOuterClick = function() {
console.log('Outer click')
}
let onMiddleClick = function() {
console.log('Middle click')
}
let onInnerClick = function() {
console.log('Inner click')
}
let mounted = function() {
this.$refs.outer.addEventListener('click', onOuterClick, true)
this.$refs.middle.addEventListener('click', onMiddleClick, true)
this.$refs.inner.addEventListener('click', onInnerClick, true)
}
export default {
mounted
}
</script>
22 行
let mounted = function() {
this.$refs.outer.addEventListener('click', onOuterClick, true)
this.$refs.middle.addEventListener('click', onMiddleClick, true)
this.$refs.inner.addEventListener('click', onInnerClick, true)
}
若要實現 Event Capturing,標準做法是使用 addEventListener()
註冊 event handler,且在第 3 個 argument 傳 true
。
Capture Modifier
<template>
<div @click.capture="onOuterClick" class="p-3 bg-blue-500">
<div @click.capture="onMiddleClick" class="p-3 bg-green-500">
<div @click.capture="onInnerClick" class="bg-red-500">Click Me</div>
</div>
</div>
</template>
<script>
let onOuterClick = function() {
console.log('Outer click')
}
let onMiddleClick = function() {
console.log('Middle click')
}
let onInnerClick = function() {
console.log('Inner click')
}
export default {
methods: {
onOuterClick,
onMiddleClick,
onInnerClick
}
}
</script>
第 2 行
<div @click.capture="onOuterClick" class="p-3 bg-blue-500">
<div @click.capture="onMiddleClick" class="p-3 bg-green-500">
<div @click.capture="onInnerClick" class="bg-red-500">Click Me</div>
</div>
</div>
Vue 提供了 capture
event modifier,讓我們在 HTML template 就能實現 Event Capturing,不必寫 JavaScript。
Conclusion
capture
event modifier 讓我們以 declarative 方式實現 Event Capturing,不必特別寫 JavaScript