根据文档了解角度js过滤器语法

时间:2014-04-08 04:07:39

标签: angularjs

根据this,“currency”过滤器将amount作为第一个参数,并给出以下语法:

{{ currency_expression | currency : amount : symbol}}

但在以下示例中,它从未将amount作为参数传递:

<span id="currency-default">{{amount | currency}}</span>

我假设示例中的amount引用了文档中编写的语法中的currency_expression。他们可以用这种方式将它写在文档中:

{{ currency_expression | currency : symbol}}

另一个示例是filter filter,其语法如下:

{{ filter_expression | filter : array : expression : comparator}}

但在以下示例中,它从未指定“源数组”参数:

<tr ng-repeat="friendObj in friends | filter:search:strict">

我假设示例中的friendObj in friends引用filter_expressionsearch引用array如果我们要遵循写入的语法文件。他们可以用这种方式将它写在文档中:

{{ filter_expression_that_returns_array | filter : expression : comparator}}

我不确定我是否遗漏了一些东西但是文档对我来说没有意义。

我的问题是,我是否应该忽略文档中第一个参数必须是输入的内容?

2 个答案:

答案 0 :(得分:1)

对于它的价值(因为根据经验,我们已经知道它就是这样),源代码表明表达式只需要在|之前。

使用 version 1.2.16 的来源,而不需要详细说明:

<强> ng/parse.js#L103

// In the OPERATORS hash:
var OPERATORS = {
    ...
    '|': function (self, locals, a, b) {
        return b(self, locals)(self, locals, a(self, locals));
    },
    ...

<强> ng/parse.js#L579

// `Parser`'s `filter()` method:
Parser.prototype = {
    ...
    filter: function() {
      var token = this.expect();
      var fn = this.$filter(token.text);
      var argsFn = [];
      while (true) {
        if ((token = this.expect(':'))) {
          argsFn.push(this.expression());
        } else {
          var fnInvoke = function(self, locals, input) {
            var args = [input];
            for (var i = 0; i < argsFn.length; i++) {
              args.push(argsFn[i](self, locals));
            }
            return fn.apply(self, args);
          };
          return function() {
            return fnInvoke;
          };
        }
      }
    },
    ...

那么,我们学到了什么?

if ((token = this.expect(':'))) {
  argsFn.push(this.expression());

解析器将在过滤器之后获取所有标记(由:分隔)并将它们放入数组(argsFn)。


var args = [input];
for (var i = 0; i < argsFn.length; i++) {
  args.push(argsFn[i](self, locals));
}

在&#34;运行时&#34; (当实际过滤是hapenning时)将创建一个新数组(args),该数组将包含input但是什么是输入?后面的更多内容)和每个参数先前存储在argsFn中的令牌。


return fn.apply(self, args);

args数组将是过滤函数的参数列表。

因此,args包含input以及filter_name之后的代币(如expression | filter_name : param1 : param2所示)。
如果我们可以说服自己input确实是表达式(出现在|的左侧),那么我们应该确信没有必要将表达式显示为第一个参数之后 filter_name


var fnInvoke = function(self, locals, input) {
...
return function() {
  return fnInvoke;
};

filter()返回一个匿名函数,该函数在执行时返回函数fnInvoke inputfnInvoke执行时的第三个参数。


现在让我们回到|运营商:

'|': function (self, locals, a, b) {
    ...

这将导致调用此匿名函数,其中ab分别是左侧(expression)和右侧(filter_name:param1:param2) 。
<子> (实际上ab不是左侧和右侧,但它们是在执行时返回在给定上下文中评估左侧和右侧的结果的函数(即范围)。


return b(self, locals)(self, locals, a(self, locals));

这告诉我们通过调用filter()b(self, locals))返回的匿名函数返回的函数将使用以下参数执行:

`self`, `locals`, `a(self, locals)`

这意味着神秘的input参数(记住它是fnInvoke的第3个参数?)是a(self, locals)
并且a(self, locals)基本上是在当前范围的上下文中评估|运算符的左侧参数的结果,例如将字符串('someExpression')计算为当前范围($scope.someExpression)中属性值的结果。


我不知道你是否相信(我不认为我会这样)。
我从解释中留下了很多细节,但感兴趣的读者可以深入研究这个来源并说服自己:)

<子> 我觉得发布如此冗长的答案而且实用价值很小,我觉得有点不好。叹...

答案 1 :(得分:-1)

就个人而言,如果有疑问,我会一直阅读源代码。

对于您的<span id="currency-default">{{amount | currency}}</span>示例:

https://github.com/angular/angular.js/blob/master/src/ng/filter/filters.js#L50

currencyFilter.$inject = ['$locale'];
function currencyFilter($locale) {
  var formats = $locale.NUMBER_FORMATS;
  return function(amount, currencySymbol){
    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;
    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).
                replace(/\u00A4/g, currencySymbol);
  };
}

我认为amount然后是currency,所以输入必须是第一个参数。

<强>更新

HTML模板绑定上下文中filter的来源。

https://github.com/angular/angular.js/blob/master/src/ng/filter/filter.js#L116

function filterFilter() {
  return function(array, expression, comparator) {
    if (!isArray(array)) return array;

首先if检查array,即输入,作为第一个参数。