$ parse()的第二个参数是什么?

时间:2015-01-29 17:02:53

标签: angularjs

今天,我在查看ngOptions.js来源时遇到了这个问题:

getWatchables: $parse(valuesFn, function(values) {
        // Create a collection of things that we would like to watch (watchedArray)
        // so that they can all be watched using a single $watchCollection
        // that only runs the handler once if anything changes
        var watchedArray = [];
        values = values || [];

        Object.keys(values).forEach(function getWatchable(key) {
          var locals = getLocals(values[key], key);
          var label = displayFn(scope, locals);
          var selectValue = getTrackByValue(values[key], locals);
          watchedArray.push(selectValue);
          watchedArray.push(label);
        });
        return watchedArray;
      }),

但是$parse的官方文档没有指定任何第二个参数。

它做了什么?

1 个答案:

答案 0 :(得分:2)

<强>来源

V1.3.4:

function addInterceptor(parsedExpression, interceptorFn) {
  if (!interceptorFn) return parsedExpression;
  var watchDelegate = parsedExpression.$$watchDelegate;

  var regularWatch =
      watchDelegate !== oneTimeLiteralWatchDelegate &&
      watchDelegate !== oneTimeWatchDelegate;

  var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {
    var value = parsedExpression(scope, locals);
    return interceptorFn(value, scope, locals);
  } : function oneTimeInterceptedExpression(scope, locals) {
    var value = parsedExpression(scope, locals);
    var result = interceptorFn(value, scope, locals);
    // we only return the interceptor's result if the
    // initial value is defined (for bind-once)
    return isDefined(value) ? result : value;
  };

  // Propagate $$watchDelegates other then inputsWatchDelegate
  if (parsedExpression.$$watchDelegate &&
      parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
    fn.$$watchDelegate = parsedExpression.$$watchDelegate;
  } else if (!interceptorFn.$stateful) {
    // If there is an interceptor, but no watchDelegate then treat the interceptor like
    // we treat filters - it is assumed to be a pure function unless flagged with $stateful
    fn.$$watchDelegate = inputsWatchDelegate;
    fn.inputs = [parsedExpression];
  }

  return fn;
}

根据上面的示例和angularjs的来源,第二个参数允许您将 transform-like 逻辑应用于解析结果。

查看https://github.com/angular/angular.js/blob/master/src/ng/directive/ngOptions.js#L461

// We will re-render the option elements if the option values or labels change
scope.$watchCollection(ngOptions.getWatchables, updateOptions);

似乎,它用于为ngOptions来源中的手表提供单一方式。它会在更改名称和/或标签时触发。如果不使用,手表只能用于更换标签或仅用于更改价值,而不是两者兼而有之。

角度代码中使用的其他样本

1。观看ng-bind

  var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
    return (value || '').toString();
  });

这里我们构建一个基于$ parse值转换为字符串的监视器。似乎在$ digest周期中进行了更好,更简单的比较。

2。手表在&#39; =&#39; -scoped指令参数

var parentValueWatch = function parentValueWatch(parentValue) {
  if (!compare(parentValue, isolateBindingContext[scopeName])) {
  // we are out of sync and need to copy
  if (!compare(parentValue, lastValue)) {
  // parent changed and it has precedence
  isolateBindingContext[scopeName] = parentValue;
  } else {
  // if the parent can be assigned then do so
  parentSet(scope, parentValue = isolateBindingContext[scopeName]);
}
}
return lastValue = parentValue;
};

如您所见,我们只是根据脏检查保持范围值同步。这就是为什么我们需要第二个$ digest-cycle来触发指令的内部监视。


<强>摘要

似乎它是一种从繁重的东西转变为简单的东西的方式,在$ digest-cycle中,简单的=可以与之形成对比。如果我们触发手表,我们需要得出结论。

它也可以用作为手表设置通用逻辑的方法。它允许编写一次,并在我们需要$ parsed值时用于所有情况。