关于AngularJs数据递归呈现的实现的几种方式

https://www.lyblog.net/detail/596.html

 

在实践中,常常会有数据结构一致但深度不确定的数据。而通常情况下,对数据的处理会用到递归的方式。例如网站的无限级分类的展现,分类数据结构:

复制
  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(typeof template != "string") return ;
  9. return template.replace(/\{\w+\}/gi, function(matchs) {
  10. var returns = scope[matchs.replace(/(\{)|(\})/g, "")];
  11. return (returns + "") == "undefined"? "": returns;
  12. });
  13. }
  14.  
  15. /**
  16. * 解析并插入分类
  17. */
  18. $('#category').append(function(){
  19. var template = '<a href="{cateId}.html">{cateName}</a>';
  20. var ret = (function(c){
  21. if(!c || !c.length) return '';
  22. var ret = '<ul>';
  23. for(var i = 0, j = c.length; i < j; i++){
  24. ret += '<li>';
  25. ret += templateParse(template, c[i]);
  26. ret += arguments.callee(c[i].child);
  27. ret += '</li>';
  28. }
  29. return (ret + '</ul>');
  30. })(cate);
  31.  
  32. return ret;
  33. });

以上页面可以点击"jq实现无限级分类展示演示DEMO",查看对应结果。

angularJs中基于模板递归的实现

同样的原理,可以通过组合angularJs内置的ng-includeng-init来达到递归的效果,示例模板如下:

复制
  1. <script id="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. <div ng-app="demo">
  2. <div ng-controller="demo">
  3. <ul ng-include="'recursion'"></ul>
  4. </div>
  5. </div>

实现效果演示DEMO,"AngularJ基于模板递归实现分类展示"

基于指令递归的实现

同样的道理,在指令中,咱们可以这么来干(内容参考自angular-recursion):

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

关于recursion指令

以上两种方式实现与模板耦合的过于紧密,有没有办法可以像如下的方式来使用呢?(未完,等续)

复制
  1. <ul recursion="cate">
  2. <li ng-repeat="item in cate">
  3. <a href="{{item.cateId}}">{{item.cateName}}</a>
  4. <ul recursion-child='item.child'></ul>
  5. </li>
  6. </ul>
posted @ 2018-05-08 17:22  callmeguxi  阅读(956)  评论(0编辑  收藏  举报