研究下attachInternals方法,可让普通元素有表单特性

这篇文章发布于 2025年03月23日,星期日,23:34,归类于 HTML相关, JS API。 阅读 585 次, 今日 150 次 3 条评论

 

封面占位图

本文又是独家内容,因为持续学习的人本就不多,持续关注前沿技术的人就更少,而关注自定义元素和原生表单特性的就更少,所以,也就我这样的老人家会研究并撰写相关的知识了。

可惜,现在做这类文字输出的收益极低,因为大家只能通过我的社交媒体账户获取,随着AI的日益普及,传统搜索引擎注定没落,而AI把我辛苦写的内容一抓,然后自己“思考”一番输出给用户,我什么好处都得不到。

某种意义上,AI智能是限制了原创内容输出的动力的,尤其是独立平台的个体创作者。

好了,不吐槽了,回到正题,讲下HTML元素的全局方法attachInternals()方法,此方法用在自定义元素中,也就是我们常说的Web Components组件中,可以让自定义元素具有原生表单元素一样的特性。

此方法的使用还是挺简单的,关键是如何理解其运作原理,想了下,没有通过一个案例来介绍更直观了。

一、自定义复选框组件案例

此案例描述如下:

有一个自定义的复选框元素,通过attachInternals()方法让其行为类似于原生的checkbox类型输入框,支持验证和表单提交。

下面这个演示页面就是最终实现的效果。

您可以狠狠地点击这里:HTML attachInternals自定义元素原生表单特性demo

相关HTML如下所示:

<form id="form" action="" novalidate>
    <ui-checkbox value="1" name="agree" required tabindex="-1"></ui-checkbox> 同意协议
    <p>
        <button type="submit">提交</button>
    </p>
</form>

默认渲染效果如下图所示:

表单渲染效果

非常朴实无华的样式效果,下面关键来了,如果我们点击提交按钮,就会发现,表单内置的提示效果出现了:

提示效果

如果我们点击复选框,使其选中,然后再点击提交按钮,可以看到自定义的表单数据就像原生的输入框一样,查询字符串在URL地址上呈现出来了。

原生表单提交一样的行为

是不是还挺神奇的,那具体如何实现的呢?

二、attachInternals方法的用法

单看语法,attachInternals方法使用还是挺简单的,如下:

const someInternals = someCustomElement.attachInternals() 

然后这个someInternals对象就包含多种原生表单元素所拥有的若干属性和方法,包括:

  • setFormValue(value: string|FormData|File, state?: any),表单赋值用的。
  • form — 获取所在的表单元素。
  • setValidity(flags: Partial<ValidityState>, message?: string, anchor?: HTMLElement) — 设置验证提示类型和文字信息,可以指定锚定元素。
  • willValidate — 表单提交的时候如果会触发验证,则返回值是true.
  • validity — 验证状态,是个对象。
  • validationMessage — 错误提示验证信息。
  • checkValidity — 检查是否合法,
  • reportValidity — 出现提示信息,如果不合法。
  • labels — label[for]属性关联元素
  • 用于在元素上设置aria信息的许多其他属性或方法。

上面这些属性和方法的详细介绍,可以参见我多年前撰写的这篇文章:“checkValidity等form原生JS验证方法和属性详细介绍

然而,事情并没有上面展示的那么简单。

首先第一点,attachInternals方法只适用于自定义元素,如果是常规元素,会报错,就像下面的错误截图:

表单只能自定义元素

其次,在构建自定义元素类的时候,需要让formAssociated这个静态属性的返回值是true。

使用示意:

class UiCheckbox extends HTMLElement {
  static get formAssociated() {
    return true;
  }

  constructor() {
    super();
    this.internals = this.attachInternals();
    // ...
  }
}

customElements.define('ui-checkbox', UiCheckbox);

最后,虽说上面的代码已经可以让<ui-checkbox>元素通过自定义的internals属性访问表单元素的原生属性和方法。

但是,类似表单提交字段传值,支持原生FormData这些,并不是默认就有的,根据我的尝试,需要使用上面提到的setFormValue()方法赋值。

包括验证提示的信息也需要自己进行自定义处理。

这里,不做进一步展开,如何使用的,访问demo演示页面,页面上有完整的源代码展示。

三、评价综述

attachInternals()确实有其使用场景,但是,我对此方法的普及与应用并不看好,两个原因:

其一,学习和使用门槛略高,适合喜欢走完全自定义路线的组件开发者。
其二,当下Web流行数据提交流,而不是form行为提交流,市场不广泛。

我细想了下,要是我,会使用此方法吗?

我是个原生开发推崇之人,以LuLu UI组件举例,里面所有的控件都是基于原生表单元素实现的,包括无法轻松样式自定义的下拉框,所以,想不到需要用到attachInternals()的场景。

除非是浏览器没有的组件,而这个组件同时有表单提交或者验证的需求,例如,使用div模拟的富文本编辑器。

嗯……再看吧,说不定哪天我就遇到时候使用attachInternals()方法的场景,到时候,我再文中补充好了。

以上就是本文的全部内容,感谢阅读!

也欢迎分享,让更多人了解,我家侍女先谢过诸位了。

侍女

(本篇完)

分享到:


发表评论(目前3 条评论)

  1. chao说道:

    看着没什么人用系列

  2. Luke说道:

    好文 感谢分享
    话说大佬的错误截图用的是宋体英文吗 看着好出戏