“需要”在哪里实际添加到DOM?

时间:2018-05-10 14:46:41

标签: angularjs angularjs-directive

我很难理解angularjs如何修改DOM,特别是关于ng-required指令。 ng-required指令(from GitHub):

var requiredDirective = function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, elm, attr, ctrl) {
      if (!ctrl) return;
      attr.required = true; // force truthy in case we are on non input element

      ctrl.$validators.required = function(modelValue, viewValue) {
        return !attr.required || !ctrl.$isEmpty(viewValue);
      };

      attr.$observe('required', function() {
        ctrl.$validate();
      });
    }
  };
};

我已经使用Chrome的调试器在函数中放置了断点,而且据我所知,此代码实际上并未修改DOM中所需的值,但我可以看到required="required"被添加并从中移除输入元素。在angularjs源代码中,DOM的实际修改发生了什么?

一个简单的测试表格:

        <form>
          <label>Test Select</label>
          <select ng-model="testSelect" ng-required="testIsRequired">
            <option>val 1</option>
            <option>val 2</option>
          </select>
          <label>Required
            <input type="checkbox" ng-model="testIsRequired" />
          </label>

          <label>Output</label>
          <p>
            Test is required:  {{testIsRequired}}
          </p>
          <p>
            Select Value: {{testSelect}}
          </p>
        </form>

1 个答案:

答案 0 :(得分:0)

我终于设法在正确的地方找到了一个断点。 AngularJS为'boolean'属性设置了默认链接函数('required','disabled'等),但'multiple'属性除外。

监视布尔属性,$set attr方法用于更改DOM。

似乎问题中的实际requiredDirective仅在更改ng-required值时处理更新验证。

相关代码(同样来自GitHub):

var ngAttributeAliasDirectives = {};

// boolean attrs are evaluated
forEach(BOOLEAN_ATTR, function(propName, attrName) {
  // binding to multiple is not supported
  if (propName === 'multiple') return;

  function defaultLinkFn(scope, element, attr) {
    scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
      attr.$set(attrName, !!value);
    });
  }

  var normalized = directiveNormalize('ng-' + attrName);
  var linkFn = defaultLinkFn;

  if (propName === 'checked') {
    linkFn = function(scope, element, attr) {
      // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input
      if (attr.ngModel !== attr[normalized]) {
        defaultLinkFn(scope, element, attr);
      }
    };
  }

  ngAttributeAliasDirectives[normalized] = function() {
    return {
      restrict: 'A',
      priority: 100,
      link: linkFn
    };
  };
});