新手问题 问一个 AngularJS 的问题,不知道如何写才比较优雅。。

wcp1231 · 2013年12月16日 · 最后由 wcp1231 回复于 2013年12月16日 · 3849 次阅读

AngularJS 里显示一个过滤后的数组的数据,很简单:

<ul>
  <li ng-repeat="item in data | filter:query">
    {{item}}
  </li>
</ul>

接下来我想显示数据的长度,不知道怎么写比较优雅。。我想到的两个方法都感觉不好: 第一种过滤了两次,不好。

<span>{{(item in data | filter:query).length}}</span>
<ul>
  <li ng-repeat="item in data | filter:query">
    {{item}}
  </li>
</ul>

第二种,写法有点特别。

<span>{{tempData.length}}</span>
<ul>
  <li ng-repeat="item in (tempData = (data | filter:query))">
    {{item}}
  </li>
</ul>

但感觉都不太优雅。。。求大神指点。。。

要是从这两种里选的话,我选第一种写法。更简洁

第一种要执行两次 filter 的,性能弱些;第二种则 cache 了 filter 的结果,明显更优。

如果你一定要在模板上处理的话,第二种已然是最优解了(仅我所知);但是你依然可以尝试在 Controller 里直接获取 filter 的结果:

yourApp.controller("YourController", [
  "$scope",
  "$filter",
  function ($scope, $filter) {
    $scope.$watch('query', function (new, old) { // 监听 query,得到两个参数:新值和旧值
      // 下面这句等价于 "item in data | filter:query" 只不过我们用 new 来直接拿用户输入的 query
      // 然后把返回结果交给 $scope 下的一个新对象,例如 filteredArray
      $scope.filteredArray = $filter('filter')($scope.data, new);
    });
  }
]);

这个好处就是你可以对结果集合做任何处理,不仅仅只是拿到 filteredArray.length 而已了,一些稍微复杂的操作(比如要 map 的)是不好在模板里直接搞的。

#1 楼 @loveky 可是这样的话就执行几次过滤了,如果东西更多。。

<span ng-hide="item in data | filter:query).length">没有数据</span>
<div ng-show="item in data | filter:query).length">
  <span>{{(item in data | filter:query).length}}</span>
  <ul>
    <li ng-repeat="item in data | filter:query">
      {{item}}
    </li>
  </ul>
</div>

感觉就很重复了。。

#2 楼 @nightire 嗯。。我也感觉在controller比较好。第二种虽然优化了性能,不过感觉有点乱

#3 楼 @wcp1231 我更喜欢第一种方法的原因是第二种写法在读 code 时会很难受。第一次看到 tempData 的时候,我不知道它是哪来的,代表什么意思。。。

#4 楼 @wcp1231 ng 里经常这么写的,若不需进一步处理的话,直接在模板里 cache 是很常见的手法,用多了也就习惯了。

当然了,有节操的程序员的确不喜欢在模板里搞花样,无非就是在 Controller 里打代码稍微累些,但是伸缩性也好,代码也漂亮,易于维护。

无论如何像第一种那样都是不可取的,就像你后来演示的例子一样,一旦用在多处,性能就会大大降低,代码也不再简洁了。

#5 楼 @loveky 我名字没起好。。不过确实不直观。我找了好久临时变量的写法,只发现了这个。。 #6 楼 @nightire 也就是说在模板里 cache 比较方面也常见,在 controller 里搞则比较好看且以维护咯。谢谢了~

需要 登录 后方可回复, 如果你还没有账号请 注册新账号