AngularJS中'required'属性实际添加到DOM的位置在哪?
你观察得特别准——你贴的这段ng-required指令代码确实没有直接动手修改DOM里的required属性,它的核心职责是维护表单的验证规则,而你看到的DOM上required属性的添删,是AngularJS的属性绑定系统和表单元素的原生指令协作完成的。
先说说你贴的这段指令代码干了啥
先拆解一下这段requiredDirective的作用:
- 它给
NgModelController加了个$validators.required验证器,用来判断输入值是否为空(只有当required为true时才会触发这个验证)。 - 它通过
attr.$observe('required', ...)监听required属性的变化,一旦属性值变了就触发重新验证,保证验证状态是最新的。 - 开头的
attr.required = true只是打个补丁,避免在非输入元素上出现异常,并不是直接修改DOM的操作。
简单说,这段代码只管“验证逻辑对不对”,不管“DOM属性改不改”。
那实际改DOM的逻辑在哪儿?
AngularJS里的表单元素(比如input、select)都有自己对应的原生指令,这些指令才是负责把属性变化同步到DOM上的“执行者”。
举个例子,你测试代码里用的select元素,它的selectDirective就会监听required属性的变化,一旦发现属性值变了,就直接调用原生DOM API去修改元素的属性——比如用elm.setAttribute('required', 'required')添上属性,或者用elm.removeAttribute('required')删掉它。
另外,你在指令里拿到的attr参数不是原生的DOM属性对象,是AngularJS封装过的。当ng-required绑定的表达式(比如你的testIsRequired)变化时,AngularJS的解析器会先更新attr.required的值,然后表单元素的指令会自动把这个变化同步到真实的DOM上。
如果你翻AngularJS的源码,在src/ng/directives/select.js或者src/ng/directives/input.js里,能找到类似这样的核心逻辑:
// 模拟select指令中同步required属性的简化代码 link: function(scope, elm, attr, ctrl) { attr.$observe('required', function(isRequired) { if (isRequired) { elm.setAttribute('required', 'required'); } else { elm.removeAttribute('required'); } }); }
对应你的测试案例理一遍流程
当你勾选那个checkbox时:
testIsRequired的值变化,触发ng-required指令里的attr.$observe回调,调用ctrl.$validate()重新跑一遍验证。- 同时,
select指令的属性监听逻辑也会感知到required属性的变化,立刻把这个变化同步到DOM上,所以你能看到DOM里的required="required"一会儿出现一会儿消失。
最后总结一下
ng-required的核心是管验证规则,不是直接改DOM。- DOM属性的同步是表单元素的原生指令+ AngularJS的
attr属性系统共同完成的。 - 想找源码里的具体位置,去
input.js或者select.js里搜required相关的逻辑就行。
内容的提问来源于stack exchange,提问作者lucasvw

