国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

Angular中實現(xiàn)樹形結(jié)構(gòu)視圖實例代碼

2019-11-19 16:39:54
字體:
供稿:網(wǎng)友

近兩年當(dāng)中使用Angular開發(fā)過很多項目,其中也涉及到一些樹形結(jié)構(gòu)視圖的顯示,最近的在項目中封裝了大量的組件,一些組件也有樹形結(jié)構(gòu)的展示,所以寫出來總結(jié)一下。

相信大家都知道,樹結(jié)構(gòu)最典型的例子就是目錄結(jié)構(gòu)了吧,一個目錄可以包含很多子目錄,子目錄又可以包含若干個子孫目錄,那咱們今天就以目錄結(jié)構(gòu)為例來說明一下Angular中樹結(jié)構(gòu)的實現(xiàn)。

首先,我們希望封裝一個組件,用于顯示整個目錄的樹形機(jī)構(gòu),代碼如下:

<!DOCTYPE html> <html ng-app="treeDemo">  <body>   <div ng-controller="TreeController">     <folder-tree current-folder="folder"></folder-tree>   </div>   <script src="node_modules/angular/angular.min.js"></script>   <script src="js/app.js"></script>  </body> </html> 

就像上面的代碼一樣,我們直接聲明folder-tree標(biāo)簽,將controller中的folder數(shù)據(jù)作為參數(shù)傳遞進(jìn)去,預(yù)期會顯示出一個完整的樹狀目錄結(jié)構(gòu)。接下來我們就來定義模塊,控制器,以及相應(yīng)的指令部分:

angular.module('treeDemo', [])  .controller("TreeController", function($scope) {   $scope.folder = {     name: 'techs',     children: [       {         name: 'server-side',         children: [           {             name: 'Java'           },           {             name: 'Python'           },           {             name: 'Node'           }         ]       },       {         name: 'front-end',         children: [           {             name: 'jQuery'           },           {             name: 'Angular'           },           {             name: 'React'           }         ]       }     ]   }  })  .directive("folderTree", function() {   return {     restrict: "E",     scope: {       currentFolder: '='     },     templateUrl: 'template/tree.html'   };  }); 

如上所述,在控制器中我們在$scope中綁定了一個folder的數(shù)據(jù)對象,包含整個的目錄結(jié)構(gòu)數(shù)據(jù),接著定義了folderTree指令,它會使用tree.html作為模板進(jìn)行視圖渲染,我們這就來look look模板中的內(nèi)容:

<p>{{currentFolder.name}}</p> <ul>   <li ng-repeat="subfolder in currentFolder.children">     <folder-tree current-folder="subfolder"></folder-tree>   </li> </ul> 

可以看到,在模板中有個很重要的環(huán)節(jié),那就是使用ng-repeat指令遍歷當(dāng)前目錄的子集,然后再次使用folder-tree組件來渲染相應(yīng)的子目錄,這種方式簡直是完美,現(xiàn)在我們來看看渲染的結(jié)果:

這種在模板中嵌套使用指令的方法很完美,只可惜低版本的Angular中是無法實現(xiàn)的,會出現(xiàn)無限遞歸循環(huán),造成頁面假死,這是Angular本身的解析機(jī)制造成的。經(jīng)測試,Angular 1.5.0及以上版本是沒有問題的,但在Angular 1.4.9及以下版本中就會運(yùn)行失敗。假如你在項目中真的使用了低版本的Angular并且造成運(yùn)行失敗,我們還可以稍微改動一下模板,采用ng-include來實現(xiàn)同樣的功能:

<p>{{currentFolder.name}}</p> <ul>   <li ng-repeat="subfolder in currentFolder.children"      ng-include="'template/tree.html'"      ng-init="currentFolder = subfolder">   </li> </ul> 

我們在模板中去掉了folder-tree指令,使用了ng-include指令,再次將tree.html模板引入進(jìn)來,需要注意的是,因為ng-include會創(chuàng)建一個獨(dú)立的作用域,為了讓其正確的引用到currentFolder變量,我們需要在每個ng-include中初始化currentFolder,將其賦值為ng-repeat中的當(dāng)前subfolder,另外,別忘了ng-include指令中模板路徑前后加上單引號。

這樣確實可以,但是你可能覺得有些遺憾,沒能使用最好的解決方案來實現(xiàn)這個樹結(jié)構(gòu)。

其實這個問題早就有人吐槽了,令人驚喜的是,有個叫Mark的伙計寫了一個service專門解決這個問題:

/*  * An Angular service which helps with creating recursive directives.  * @author Mark Lagendijk  * @license MIT  */ angular.module('RecursionHelper', []).factory('RecursionHelper', ['$compile', function($compile){   return {     /**      * Manually compiles the element, fixing the recursion loop.      * @param element      * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.      * @returns An object containing the linking functions.      */     compile: function(element, link){       // Normalize the link parameter       // 如果link參數(shù)是對象類型link:{pre: function(...){}, post: function(...){}}則不做處理       // 如果link參數(shù)是函數(shù)類型則將其作為post-link函數(shù)在$compile之后調(diào)用       if(angular.isFunction(link)){         link = { post: link };       }        // Break the recursion loop by removing the contents       // 獲取并清空當(dāng)前元素的內(nèi)容,后面進(jìn)行編譯       var contents = element.contents().remove();       var compiledContents;        return {         pre: (link && link.pre) ? link.pre : null,         /**          * Compiles and re-adds the contents          * 編譯和重新添加內(nèi)容到當(dāng)前元素          */         post: function(scope, element){           // Compile the contents           if(!compiledContents){             compiledContents = $compile(contents);           }           // Re-add the compiled contents to the element           compiledContents(scope, function(clone){             element.append(clone);           });            // Call the post-linking function, if any           if(link && link.post){             link.post.apply(null, arguments);           }         }       };     }   }; }]); 

現(xiàn)在我們只需引入這個模塊,然后在directive中使用RecursionHelper這個service,調(diào)用其compile手動編譯指令對應(yīng)的元素節(jié)點:

angular.module('treeDemo', ['RecursionHelper'])  .controller("TreeController", function($scope) {   $scope.folder = {     name: 'techs',     children: [       {         name: 'server-side',         children: [           {             name: 'Java'           },           {             name: 'Python'           },           {             name: 'Node'           }         ]       },       {         name: 'front-end',         children: [           {             name: 'jQuery'           },           {             name: 'Angular'           },           {             name: 'React'           }         ]       }     ]   }  })  .directive("folderTree", function(RecursionHelper) {   return {     restrict: "E",     scope: {       currentFolder: '='     },     templateUrl: 'template/tree.html',     compile: function(element) {       // 我們這里使用RecursionHelper的compile方法編譯指令當(dāng)前元素,這里第二個參數(shù)指定一個函數(shù),相當(dāng)于常用的link函數(shù)       // 當(dāng)然我們也可以指定一個對象,里面包含pre和post函數(shù),分別對應(yīng)pre-link和post-link       return RecursionHelper.compile(element, function(scope, iElement, iAttrs, controller, transcludeFn){         // Define your normal link function here.         // Alternative: instead of passing a function,         // you can also pass an object with          // a 'pre'- and 'post'-link function.          // 這里可以往scope中綁定一些變量         scope.variable = 'hello world';       });     }   };  }); 

在上面代碼中,我們在創(chuàng)建treeDemo模塊時引入RecursionHelper模塊,然后在創(chuàng)建folderTree指令時使用RecursionHelper服務(wù),并且在compile方法中調(diào)用RecursionHelper的compile方法,即可修復(fù)上面的問題。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 鱼台县| 叙永县| 湄潭县| 普陀区| 青海省| 大关县| 巫山县| 南丹县| 馆陶县| 商丘市| 同心县| 泊头市| 开鲁县| 清水河县| 河曲县| 临桂县| 平陆县| 迁安市| 县级市| 普格县| 乐安县| 华安县| 兴文县| 红原县| 秦皇岛市| 康马县| 铁力市| 光山县| 通州市| 新乡市| 兴宁市| 玛沁县| 平江县| 黄大仙区| 土默特右旗| 福州市| 沂南县| 龙井市| 马龙县| 遂溪县| 祁连县|