您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Angular中如何實現(xiàn)樹形結(jié)構(gòu)視圖”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學習一下“Angular中如何實現(xiàn)樹形結(jié)構(gòu)視圖”這篇文章吧。
首先,我們希望封裝一個組件,用于顯示整個目錄的樹形機構(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標簽,將controller中的folder數(shù)據(jù)作為參數(shù)傳遞進去,預期會顯示出一個完整的樹狀目錄結(jié)構(gòu)。接下來我們就來定義模塊,控制器,以及相應的指令部分:
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作為模板進行視圖渲染,我們這就來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指令遍歷當前目錄的子集,然后再次使用folder-tree組件來渲染相應的子目錄,這種方式簡直是完美,現(xiàn)在我們來看看渲染的結(jié)果:
這種在模板中嵌套使用指令的方法很完美,只可惜低版本的Angular中是無法實現(xiàn)的,會出現(xiàn)無限遞歸循環(huán),造成頁面假死,這是Angular本身的解析機制造成的。經(jīng)測試,Angular 1.5.0及以上版本是沒有問題的,但在Angular 1.4.9及以下版本中就會運行失敗。假如你在項目中真的使用了低版本的Angular并且造成運行失敗,我們還可以稍微改動一下模板,采用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模板引入進來,需要注意的是,因為ng-include會創(chuàng)建一個獨立的作用域,為了讓其正確的引用到currentFolder變量,我們需要在每個ng-include中初始化currentFolder,將其賦值為ng-repeat中的當前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 // 獲取并清空當前元素的內(nèi)容,后面進行編譯 var contents = element.contents().remove(); var compiledContents; return { pre: (link && link.pre) ? link.pre : null, /** * Compiles and re-adds the contents * 編譯和重新添加內(nèi)容到當前元素 */ 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手動編譯指令對應的元素節(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方法編譯指令當前元素,這里第二個參數(shù)指定一個函數(shù),相當于常用的link函數(shù) // 當然我們也可以指定一個對象,里面包含pre和post函數(shù),分別對應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服務,并且在compile方法中調(diào)用RecursionHelper的compile方法,即可修復上面的問題。
以上是“Angular中如何實現(xiàn)樹形結(jié)構(gòu)視圖”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。