自定义表单控件需继承HTMLElement并设formAssociated=true,调用attachInternals()获取ElementInternals,暴露value/name/disabled等属性及checkValidity()等校验接口,通过setValidity()集成规则,内部须含可聚焦元素以支持交互与提示定位。

自定义表单控件要支持校验规则,核心是让浏览器识别它为“可表单关联的元素”,并正确参与 form.checkValidity()、form.reportValidity() 和原生提交流程。关键在于继承 HTMLElement 并实现 formAssociated = true,同时暴露标准属性(如 value、name、disabled)和校验相关接口(如 validity、validationMessage、checkValidity()、setCustomValidity())。
继承 HTMLElement 并启用表单关联
必须在构造函数中设置 this.formAssociated = true,这是触发浏览器自动绑定表单、收集值、执行校验的前提。不设这个,后续所有校验逻辑都不会被表单系统感知。
- 使用
ElementInternals管理内部状态:调用this.attachInternals()获取 internals 对象,它提供setValidity()、reportValidity()等能力 - 避免手动监听
formdata或submit事件来模拟——应依赖原生机制 - 示例初始化:
class MyInput extends HTMLElement {
constructor() {
super();
this.formAssociated = true;
this.internals = this.attachInternals();
this._value = '';
}
}
customElements.define('my-input', MyInput);
</script>
暴露标准属性与 getter/setter
表单控件需像原生 <input> 一样响应 name、value、disabled、required 等属性变更,并同步更新内部状态和校验结果。
-
value必须有 getter 和 setter:setter 中调用this.internals.setFormValue(this._value)向表单提交数据 - 监听
attributeChangedCallback响应required、disabled等变化,并调用this.internals.setValidity(...)更新校验状态 - 例如:
required属性变化时,若当前为空值,应标记为valueMissing
集成校验规则与错误消息
校验逻辑由你定义,但需通过 ElementInternals.setValidity() 告知浏览器结果。该方法接收三个参数:flags(ValidityState 键值对)、message(自定义错误文本)、anchor(可选,用于聚焦定位)。
- 在
checkValidity()方法中执行你的规则(如邮箱格式、最小长度),然后调用this.internals.setValidity(...) - 重写
reportValidity()可选,通常直接委托给this.internals.reportValidity() -
setCustomValidity(message)应保存 message 并在下次checkValidity()中参与判断(空字符串表示无自定义错误) - 示例规则:输入含空格则报错
{ customError: true },并设 message 为 “不能包含空格”
确保 DOM 结构与交互符合预期
虽然逻辑在 JS 中,但用户操作仍需作用于真实可聚焦/可编辑的子元素(如内部 <input> 或 <textarea>),否则无法获得焦点、无法输入、校验提示框(popup)也无法准确定位。
- 内部必须有一个可聚焦的替换元素(
input、textarea、或带tabindex="0"的容器) - 重写
focus()、blur()方法,代理到内部元素 - 监听内部元素的
input、change事件,更新this._value并触发校验 - 注意:不要阻止原生事件传播,否则
formdata事件可能收不到值


















