1. 程式人生 > >關於AngularJs資料遞迴呈現的實現的幾種方式

關於AngularJs資料遞迴呈現的實現的幾種方式

在實踐中,常常會有資料結構一致但深度不確定的資料。而通常情況下,對資料的處理會用到遞迴的方式。例如網站的無限級分類的展現,分類資料結構:

複製
  1. var cate =[
  2. {
  3. cateId:1,
  4. cateName:'前端技術',
  5. child:[
  6. {
  7. cateId:4,
  8. cateName:'JavaScript'
  9. },
  10. ...
  11. ]
  12. },
  13. {
  14. cate:2,
  15. cateName:'後端技術',
  16. child:[
  17. {
  18. cateId:3,
  19. cateName
    :'PHP',
  20. child:[
  21. {
  22. cateId:6,
  23. cateName:'ThinkPHP'
  24. },
  25. ...
  26. ]
  27. }
  28. ]
  29. }
  30. ];

用jq常常通過如下方式實現,示例程式碼如下:

複製
  1. /**
  2. * * 解析模板檔案
  3. * @param template 模板字串
  4. * @param scope 模板作用域
  5. * return [string] 解析過後的字串
  6. */
  7. function templateParse(template, scope){
  8. if(typeoftemplate!="string"
    )return;
  9. returntemplate.replace(/\{\w+\}/gi,function(matchs){
  10. var returns = scope[matchs.replace(/(\{)|(\})/g,"")];
  11. return(returns +"")=="undefined"?"": returns;
  12. });
  13. }
  14. /**
  15. * 解析並插入分類
  16. */
  17. $('#category').append(function(){
  18. vartemplate='<a href="{cateId}.html">{cateName}</a>';
  19. var ret =(function(c){
  20. if(!c ||!
    c.length)return'';
  21. var ret ='<ul>';
  22. for(var i =0, j = c.length; i < j; i++){
  23. ret +='<li>';
  24. ret += templateParse(template, c[i]);
  25. ret += arguments.callee(c[i].child);
  26. ret +='</li>';
  27. }
  28. return(ret +'</ul>');
  29. })(cate);
  30. return ret;
  31. });

angularJs中基於模板遞迴的實現

同樣的原理,可以通過組合angularJs內建的ng-includeng-init來達到遞迴的效果,示例模板如下:

複製
  1. <scriptid="recursion"type="text/ng-template">
  2. <li ng-repeat="item in cate">
  3. <a href="{{item.cateId}}">{{item.cateName}}</a>
  4. <ul ng-if="item.child.length" ng-include="'recursion'" ng-init="cate=item.child"></ul>
  5. </li>
  6. </script>

呼叫方式如下:

複製
  1. <divng-app="demo">
  2. <divng-controller="demo">
  3. <ulng-include="'recursion'"></ul>
  4. </div>
  5. </div>

基於指令遞迴的實現

同樣的道理,在指令中,咱們可以這麼來幹(內容參考自angular-recursion):

複製
  1. angular.module('demo').directive('recursion',function($compile){
  2. function cpl(element, link){
  3. // Normalize the link parameter
  4. if(angular.isFunction(link)){
  5. link ={ post: link };
  6. }
  7. // Break the recursion loop by removing the contents
  8. var contents = element.contents().remove();
  9. var compiledContents;
  10. return{
  11. pre:(link && link.pre)? link.pre :null,
  12. /**
  13. * Compiles and re-adds the contents
  14. */
  15. post:function(scope, element){
  16. // Compile the contents
  17. if(!compiledContents){
  18. compiledContents = $compile(contents);
  19. }
  20. // Re-add the compiled contents to the element
  21. compiledContents(scope,function(clone){
  22. element.append(clone);
  23. });
  24. // Call the post-linking function, if any
  25. if(link && link.post){
  26. link.post.apply(null, arguments);
  27. }
  28. }
  29. };
  30. }
  31. return{
  32. restrict:'A',
  33. scope:{recursion:'='},
  34. template:'<li ng-repeat="item in recursion">\
  35. <a href="{{item.cateId}}.html">{{item.cateName}}</a>\
  36. <ul recursion="item.child">\
  37. </ul>\
  38. </li>',
  39. compile:function(element){
  40. return cpl(element,function(scope, iElement, iAttrs, controller, transcludeFn){
  41. // Define your normal link function here.
  42. // Alternative: instead of passing a function,
  43. // you can also pass an object with
  44. // a 'pre'- and 'post'-link function.
  45. });
  46. }
  47. };
  48. });

關於recursion指令

以上兩種方式實現與模板耦合的過於緊密,有沒有辦法可以像如下的方式來使用呢?(未完,等續)

複製
  1. <ulrecursion="cate">
  2. <ling-repeat="item in cate">
  3. <ahref="{{item.cateId}}">{{item.cateName}}</a>
  4. <ulrecursion-child='item.child'></ul>
  5. </li>
  6. </ul>

源引:http://www.lyblog.net/detail/596.html