对于对话框元素
<dialog>
,是否有某种“打开”事件在显示时被触发,无论是正常还是作为模式?
close
事件确实火了,但我似乎无法得到任何类型的open
事件。
HTML 示例:
<dialog>
<h1>Oh hey, a dialog...</h1>
</dialog>
在 JavaScript 中:
document.querySelector('dialog').addEventListener('open', (e) => {
console.log(e);
});
document.querySelector('dialog').showModal();
不,没有
open
事件。
对话框有一个
open
属性可以确定它是否打开,但不幸的是,当这个转换时没有任何事件。
解决您问题的一个简单方法是:
<dialog id="dial">
<h3> dialog element </h3>
<button id="close">x</button>
</dialog>
<button id="buttonDialog" > Open </button>
<button id="buttonDialog2"> Open 2 </button>
const
dialog = document.getElementById('dial')
, close = document.getElementById('close')
, button = document.getElementById('buttonDialog')
, button2 = document.getElementById('buttonDialog2')
;
button.addEventListener('click', event => {
dialog.showModal()
})
close.addEventListener('click', event => {
dialog.close()
})
let observer = new MutationObserver(function() {
if (event[0].attributeName == 'open') console.log('updated')
});
observer.observe(dialog, { attributes: true })
;
button2.addEventListener('click', event => {
dialog.setAttribute('open', true)
})
正如此处的评论/回答中提到的,可以使用 MutationObserver() 生成此事件。
由于这里的答案似乎非常不完整(甚至是错误的),我自己做了实验来组成一个易于利用的答案。
注意: _
<dialog>
JS 对象始终具有 open
属性,并且它是一个布尔值(true 或 false),即使该 属性 不存在于 HTML 声明中。
第一个解决方案:
(() => // IIFE => add event 'dialog-open' to all Dialog elements
{
const
OpenEvent = new CustomEvent('dialog-open')
, ObserverM = new MutationObserver( recs =>
{
recs.forEach( ({attributeName: attr, target: dial }) =>
{
if (attr === 'open' && dial.open )
dial.dispatchEvent( OpenEvent );
})
});
document.querySelectorAll('dialog').forEach( dial =>
{
ObserverM.observe( dial, { attributes: true } );
})
})() // IIFE end...
const
btShowDial = document.querySelector('#bt-show_mDialog')
, dialogBox = document.querySelector('#dialog-box')
, dialBForm = document.querySelector('#dialog-box form')
;
btShowDial.onclick =_=>
{
dialogBox.showModal()
}
dialogBox.addEventListener('dialog-open', () =>
{
dialBForm.inNum.valueAsNumber = 0 | Math.random() *10**4
dialogBox.returnValue = 'exit with Escape key'
})
dialogBox.onclose=_=>
{
console.log(`${dialBForm.inNum.value } is ${dialogBox.returnValue}` )
}
<button id="bt-show_mDialog">show modal dialog..</button>
<dialog id="dialog-box">
<form method="dialog">
<h3>Dialog -1-</h3>
<label> mumeric : <input type="number" name="inNum"></label>
<br>
<button value="good"> good </button>
<button value="bad" > bad </button>
</form>
</dialog>
就我个人而言,我更喜欢直接在 DOM 对象上使用他们的事件方法。
它们的优点是独特,并且使代码更具可读性。
因此不妨添加这个,而不是创建特定的自定义事件!
第二个解决方案:
(() => // IIFE => add event 'dialog-open' to all Dialog elements
{
const Dialogs = document.querySelectorAll('dialog');
Dialogs.forEach( dial => dial.onOpen = function(){} ) // add onOpen empty method.
const ObserverM = new MutationObserver( recs =>
{
recs.forEach( ({attributeName: attr, target: dial }) =>
{
if (attr === 'open' && dial.open ) dial.onOpen(); // call onOpen Method...
})
});
Dialogs.forEach( dial => ObserverM.observe( dial, { attributes: true }))
})() // IIFE end...
const
btShowDial = document.querySelector('#bt-show_mDialog')
, dialogBox = document.querySelector('#dialog-box')
, dialBForm = document.querySelector('#dialog-box form')
;
btShowDial.onclick =_=>
{
dialogBox.showModal()
}
dialogBox.onOpen =_=>
{
dialBForm.inNum.valueAsNumber = 0 | Math.random() *10**4
dialogBox.returnValue = 'exit with Escape key'
}
dialogBox.onclose=_=>
{
console.log(`${dialBForm.inNum.value } is ${dialogBox.returnValue}` )
}
dialog::backdrop {
background: #00ddff5d;
}
<button id="bt-show_mDialog">show modal dialog..</button>
<dialog id="dialog-box">
<form method="dialog">
<h3>Dialog -1-</h3>
<label> mumeric : <input type="number" name="inNum"></label>
<br>
<button value="good"> good </button>
<button value="bad" > bad </button>
</form>
</dialog>
找到这个帖子并想发布我的解决方案:自定义事件。
设置
document.querySelector('dialog').showModal();
呼叫后,您可以添加document.querySelector('dialog').dispatchEvent(new Event('open'));
。然后预期的document.querySelector('dialog').addEventListener('open', e => {...});
就起作用了!