当值发生变化时,为什么不会触发`attr。$ observe`回调

时间:2016-01-05 18:44:26

标签: javascript angularjs

我编写了一个验证指令multiple-pattern,它带有几个验证正则表达式:

link: function (scope, elm, attr, ctrl) {
    if (!ctrl) return;

    let validators = [];
    attr.$observe('multiplePattern', function (patterns) {
        // doesn't get there after value change
        var parsed = scope.$eval(patterns);

但我不明白为什么当控制器$observe上的变量发生变化时未触发validationRegexps回调(更改regexp变量时会触发ng-repeat的回调):< / p>

$scope.regexp = '^\\S*$';
$scope.validationRegexps = {'nospaces': '^\\S*$', 'nofirstnumber': '^[A-Za-z]'};

setTimeout(function () {
    $scope.$apply(function () {
        $scope.regexp = '[^abc]';
        $scope.validationRegexps = {'noabc': '[^abc]'};
    })
}, 5000);

用法:

<div ng-pattern="regexp" multiple-pattern="validationRegexps"></div>

2 个答案:

答案 0 :(得分:1)

$observe$watch的工作方式相同。但这两者之间的差异是$watch需要string值或expression&amp;评估每个摘要周期,其中$observe采用interpolated表达式{{validationRegexps}}

attr.$observe仅在您使用attribute内插内容{{}}时才有效。

<强> HTML

<div ng-pattern="regexp" multiple-pattern="{{validationRegexps}}"></div>

答案 1 :(得分:0)

我刚检查了源代码,似乎有ng-pattern值的特殊处理,允许$observe正确工作而不指定插值:

var ALIASED_ATTR = {
  'ngMinlength': 'minlength',
  'ngMaxlength': 'maxlength',
  'ngMin': 'min',
  'ngMax': 'max',
  'ngPattern': 'pattern'
};


forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {
  ngAttributeAliasDirectives[ngAttr] = function() {
    return {
      priority: 100,
      link: function(scope, element, attr) {
        //special case ngPattern when a literal regular expression value
        //is used as the expression (this way we don't have to watch anything).
        if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") {
          var match = attr.ngPattern.match(REGEX_STRING_REGEXP);
          if (match) {
            attr.$set("ngPattern", new RegExp(match[1], match[2]));
            return;
          }
        }

        scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {
          // here the value is already interpolated
          attr.$set(ngAttr, value);
        });
      }
    };
  };
});

$observe

的其他用例的非插值相反
  $observe: function(key, fn) {
    var attrs = this,
        $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),
        listeners = ($$observers[key] || ($$observers[key] = []));

    listeners.push(fn);
    $rootScope.$evalAsync(function() {
      if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) {
        // not interpolated value is passed down here
        fn(attrs[key]);
      }
    });

    return function() {
      arrayRemove(listeners, fn);
    };
  }