我可以在Shadow DOM中获得一个按钮来提交不在Shadow DOM中的表单吗?



我刚刚遇到了一个有趣的情况,我在放置在<form>内的本机自定义元素的 Shadow DOM 中有一个提交<button>

  <form id="one" action="" method="get">
    <s-button>Select</s-button>
      #shadow-root
        <button>...</button>
    <button>Outside</button>
  </form>

作为<form>的直系子女,我也有<button>.

子项<button>导致表单提交。

但影根中的<button>却没有。

在某种程度上,我想这是有道理的。但是有没有人想出一种方法来告诉影根<button><form>正常工作,或者这是我必须通过 JS 处理的事情吗?

我知道点击事件在 Shadow DOM 层被阻止,但我很惊讶没有办法让按钮仍然是表单的一部分,这可以通过属性或属性进行设置。

当然,我可以捕获点击事件,然后从this发送一个新事件,但这不会做同样的事情,因为我的事件将不再是用户生成的,并且有大量与此相关的规则。

按钮

触发提交事件(在 FORM 元素上)

由于事件不能通过影子 DOM 边界(不要冒泡到父 DOM 中)

我认为这就是为什么 FORM 元素没有收到 shadowDOM 按钮(调度submit事件)的原因。

需要 Supersharps 解决方法,在轻型 DOM 中使用隐藏按钮(然后在父 DOM 中调度submit事件)

或者(从轻 DOM 开始)您找到(父)FORM 标签并自己调度提交事件:

this.closest('FORM').dispatchEvent(new Event('submit'))


关注shadowDOM和FORMS的专家:https://github.com/w3c/webcomponents/issues/187


customElements.define( 'my-button', class extends HTMLElement {
  connectedCallback() {
    this.attachShadow({mode:'open'}).innerHTML=`<button>Button In Shadow DOM</button>`
    this.onclick = _ => this.closest('FORM').dispatchEvent(new Event('submit'))
  }
})
<form onsubmit="return console.log('submit Event occured')">
    <my-button></my-button>
    <button>button in Document DOM</button>
</form>

嵌套的影子 DOM

如果 FORM 不是直接祖先,你可以这样找到它:如何使用原版 JS Web 组件从子组件引用父组件中的方法?(不是任何框架或库)

无论如何

,你都必须通过Javascript来处理它。

一个简单的解决方案是在灯光 DOM 中添加一个(遮罩的)<button>,并将click事件传输到它。

customElements.define( 's-button', class extends HTMLElement {
    connectedCallback() {
        this.attachShadow( {mode: 'open'})
            .innerHTML = `<button>In Shadow</button>`
        var submit = this.appendChild( document.createElement( 'button' ) )
        this.onclick = () => submit.click()
    }
} )
<form onsubmit="console.log('submitted');return false">
    <s-button>Select</s-button>
    <button>Outside</button>
</form>

你可以做的其他事情不完全是ShadowDOM中的按钮,如果你的button[type=submit]已入ShadowDOM中。因此,如果您有类似以下内容:

<some-component>
<button type="submit" slot="buttonSlot"></button>
</some-component>

该按钮可用于触发表单。该按钮位于轻型 DOM 中,但可以通过插槽从组件内部轻松处理。它还将保留所有适当的键盘,单击,焦点等事件,而不会遇到任何麻烦。

为了最小化轻量级 DOM html,您甚至不需要它成为type=submit您可以从组件中设置它,它仍将被视为轻量级 DOM 中任何父表单的提交按钮。

奖励(或者可能麻烦,取决于您如何看待它),它将保留页面上其他按钮的样式(除非您在组件中更改它)。

最新更新