自定义 input 类控件必须封装为独立组件,对外仅暴露受控属性(value/onchange/disabled),禁止直接操作 dom;需严格配对 label 与 id,生成唯一 id 并同步赋值;验证状态须同时使用 aria 属性与 css class;提交行为须兼容原生 form 事件流。

自定义 input 类控件必须封装为独立组件,不可直接暴露原生 input 的 DOM 操作
团队组件库中一旦出现 document.querySelector('.my-input') 或 el.addEventListener('input', ...) 这类直操作,就等于把封装层撕开了口子。后续改样式、加验证、换框架时,所有调用方都得跟着改。
- 正确做法:对外只暴露
value、onChange、disabled等受控属性,内部用<input>但不暴露其 ref - 错误模式:组件返回一个带 class 的
div包着input,却要求使用者自己去querySelector找 input 并调focus() - 兼容性陷阱:原生
input的setCustomValidity()在 Shadow DOM 中行为不一致,封装时需统一拦截并透传到内部input
label 与 id 必须严格配对,且 for 属性值必须和内部 input 的 id 一致
很多自定义控件为了“省事”,用 onClick 模拟 label 点击聚焦,结果屏幕阅读器无法识别关联关系,键盘用户 Tab 到 label 后按空格/回车无效。
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
- 每个自定义输入组件必须生成唯一
id(如用useId()或crypto.randomUUID()),并同步赋给内部input和外部label[for] - 禁止写
label[for="static-id"]—— 多个实例会冲突;也不要用label > input隐式关联,CSS 改动或 DOM 重排后极易断裂 - 若组件支持无 label 场景(如搜索框带 placeholder),需显式提供
aria-label或aria-labelledby,不能留空
验证状态必须通过 ARIA 属性和 CSS class 双通道暴露
仅靠 class="error" 不足以让辅助技术感知错误,而只写 aria-invalid="true" 又会让样式难定位。两者缺一不可。
- 验证失败时,同时设置:
aria-invalid="true"+aria-describedby="error-message-id"+class="is-invalid" -
aria-describedby指向的错误文案元素必须存在且非display: none;用visually-hidden类隐藏而非hidden属性 - 不要依赖 JS 动态增删
required或pattern属性来触发浏览器默认提示——它们在自定义控件中常被忽略,应由组件自身管理验证逻辑
表单提交行为不能绕过原生 form 事件流
常见错误是组件内用 fetch 直接发请求,导致父级 form.onsubmit 不触发、submit 按钮的 formnovalidate 失效、甚至整个表单的 reportValidity() 调用失败。
- 自定义控件必须允许被包裹在
<form></form>内,并响应submit事件;内部不应阻止冒泡,除非明确需要拦截 - 若需异步提交,应在
form.onsubmit中event.preventDefault(),而不是在控件内部提前fetch - 禁用原生提交时,必须同步设置
aria-disabled="true"和tabindex="-1",否则键盘用户仍可聚焦并按回车
input 一样可靠——这要求每处 id、每个 aria- 属性、每次事件冒泡,都经得起细看。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










