加载中...

示例:模板控制语句 for


18.13. 示例:模板控制语句 for

这个示例尝试实现一个重复语句,功能同官方的 ngRepeat ,但是使用方式类似于我们通常编程语言中的 for 语句:

  1. <div ng-controller="TestCtrl" ng-init="obj_list=[1,2,3,4]; name='name'">
  2. <ul>
  3. <for o in obj_list>
  4. <li>{{ o }}, {{ name }}</li>
  5. </for>
  6. </ul>
  7. <button ng-click="obj_list=[1,2]; name='o?'">修改</button>
  8. </div>

同样,我们从上面的使用方式去考虑这个指令的实现:

  • 这是一个完全的控制指令,所以单个节点应该只有它一个指令起作用就好了,于是权重要比较高,并且“到此为止”—— priority 设置为 1000terminal 设置为 true
  • 使用时的语法问题。事实上浏览器会把 for 节点补充成一个正确的 HTML 结构,即里面的属性都会变成类似 o="" 这样。我们通过节点的 outerHTML 属性取到字符串并解析取得需要的信息。
  • 我们把 for 节点之间的内容作为一个模板,并且通过循环多次渲染该模板之后把结果填充到合适的位置。
  • 在处理上面的那个模板时,需要不断地创建新 scope 的,并且 o 这个成员需要单独赋值。

注意:这里只是简单实现功能。官方的那个 ngRepeat 比较复杂,是做了专门的算法优化的。当然,这里的实现也可以是简单把 DOM 结构变成使用 ngRepeat 的形式 :)

JS 部分代码:

  1. 1 var app = angular.module('Demo', [], angular.noop);
  2. 2 3 app.directive('for', function($compile){
  3. 4 var compile = function($element, $attrs, $link){
  4. 5 var match = $element[0].outerHTML.match('<for (.?)=.? in=.? (.?)=.*?>');
  5. 6 if(!match || match.length != 3){throw Error('syntax: <for o in obj_list>')}
  6. 7 var iter = match[1];
  7. 8 var list = match[2];
  8. 9 var tpl = $compile($.trim($element.html()));
  9. 10 $element.empty();
  10. 1112 var link = function($scope, $ielement, $iattrs, $controller){
  11. 1314 var new_node = [];
  12. 1516 $scope.$watch(list, function(list){
  13. 17 angular.forEach(new_node, function(n){n.remove()});
  14. 18 var scp, inode;
  15. 19 for(var i = 0, ii = list.length; i < ii; i++){
  16. 20 scp = $scope.$new();
  17. 21 scp[iter] = list[i];
  18. 22 inode = tpl(scp, angular.noop);
  19. 23 $ielement.before(inode);
  20. 24 new_node.push(inode);
  21. 25 }
  22. 2627 });
  23. 28 }
  24. 2930 return link;
  25. 31 }
  26. 32 return {compile: compile,
  27. 33 priority: 1000,
  28. 34 terminal: true,
  29. 35 restrict: 'E'};
  30. 36 });
  31. 3738 app.controller('TestCtrl', angular.noop);
  32. 39 angular.bootstrap(document, ['Demo']);

还没有评论.