คำตอบสั้น ๆ : สิ่งนี้ควรทำด้วยคำสั่งที่กำหนดเองคำสั่งที่กำหนดเอง
มีคำตอบที่ยอดเยี่ยมมากมายที่นี่เช่นกัน แต่คำตอบส่วนใหญ่ที่ฉันเห็นจะพังทลายลงเมื่อคุณเริ่มใช้การคลิกภายนอกอย่างกว้างขวาง (โดยเฉพาะอย่างยิ่งหลายชั้นหรือมีการยกเว้นหลายรายการ) ฉันได้เขียนบทความเกี่ยวกับสื่อที่พูดถึงความแตกต่างของคำสั่งที่กำหนดเองและการนำไปใช้โดยเฉพาะ อาจไม่ครอบคลุมขอบเคสทั้งหมด แต่ครอบคลุมทุกอย่างที่ฉันคิดไว้
สิ่งนี้จะอธิบายการเชื่อมโยงหลายระดับการยกเว้นองค์ประกอบอื่น ๆ หลายระดับและอนุญาตให้ตัวจัดการของคุณจัดการเฉพาะ "ตรรกะทางธุรกิจ"
นี่คือรหัสสำหรับส่วนความหมายอย่างน้อยที่สุดโปรดดูบทความเพื่อดูคำอธิบายทั้งหมด
var handleOutsideClick={}
const OutsideClick = {
// this directive is run on the bind and unbind hooks
bind (el, binding, vnode) {
// Define the function to be called on click, filter the excludes and call the handler
handleOutsideClick[el.id] = e => {
e.stopPropagation()
// extract the handler and exclude from the binding value
const { handler, exclude } = binding.value
// set variable to keep track of if the clicked element is in the exclude list
let clickedOnExcludedEl = false
// if the target element has no classes, it won't be in the exclude list skip the check
if (e.target._prevClass !== undefined) {
// for each exclude name check if it matches any of the target element's classes
for (const className of exclude) {
clickedOnExcludedEl = e.target._prevClass.includes(className)
if (clickedOnExcludedEl) {
break // once we have found one match, stop looking
}
}
}
// don't call the handler if our directive element contains the target element
// or if the element was in the exclude list
if (!(el.contains(e.target) || clickedOnExcludedEl)) {
handler()
}
}
// Register our outsideClick handler on the click/touchstart listeners
document.addEventListener('click', handleOutsideClick[el.id])
document.addEventListener('touchstart', handleOutsideClick[el.id])
document.onkeydown = e => {
//this is an option but may not work right with multiple handlers
if (e.keyCode === 27) {
// TODO: there are minor issues when escape is clicked right after open keeping the old target
handleOutsideClick[el.id](e)
}
}
},
unbind () {
// If the element that has v-outside-click is removed, unbind it from listeners
document.removeEventListener('click', handleOutsideClick[el.id])
document.removeEventListener('touchstart', handleOutsideClick[el.id])
document.onkeydown = null //Note that this may not work with multiple listeners
}
}
export default OutsideClick