Angular中如何實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)視圖

這篇文章主要為大家展示了“Angular中如何實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)視圖”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Angular中如何實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)視圖”這篇文章吧。

創(chuàng)新互聯(lián)建站始終堅(jiān)持【策劃先行,效果至上】的經(jīng)營(yíng)理念,通過(guò)多達(dá)十多年累計(jì)超上千家客戶的網(wǎng)站建設(shè)總結(jié)了一套系統(tǒng)有效的全網(wǎng)營(yíng)銷解決方案,現(xiàn)已廣泛運(yùn)用于各行各業(yè)的客戶,其中包括:廣告設(shè)計(jì)等企業(yè),備受客戶贊譽(yù)。

首先,我們希望封裝一個(gè)組件,用于顯示整個(gè)目錄的樹(shù)形機(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ù)期會(huì)顯示出一個(gè)完整的樹(shù)狀目錄結(jié)構(gòu)。接下來(lái)我們就來(lái)定義模塊,控制器,以及相應(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' 
  }; 
 });

如上所述,在控制器中我們?cè)?scope中綁定了一個(gè)folder的數(shù)據(jù)對(duì)象,包含整個(gè)的目錄結(jié)構(gòu)數(shù)據(jù),接著定義了folderTree指令,它會(huì)使用tree.html作為模板進(jìn)行視圖渲染,我們這就來(lái)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>

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

Angular中如何實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)視圖

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

我們?cè)谀0逯腥サ袅薴older-tree指令,使用了ng-include指令,再次將tree.html模板引入進(jìn)來(lái),需要注意的是,因?yàn)閚g-include會(huì)創(chuàng)建一個(gè)獨(dú)立的作用域,為了讓其正確的引用到currentFolder變量,我們需要在每個(gè)ng-include中初始化currentFolder,將其賦值為ng-repeat中的當(dāng)前subfolder,另外,別忘了ng-include指令中模板路徑前后加上單引號(hào)。

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

其實(shí)這個(gè)問(wèn)題早就有人吐槽了,令人驚喜的是,有個(gè)叫Mark的伙計(jì)寫(xiě)了一個(gè)service專門解決這個(gè)問(wèn)題:

/* 
 * 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ù)是對(duì)象類型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)在我們只需引入這個(gè)模塊,然后在directive中使用RecursionHelper這個(gè)service,調(diào)用其compile手動(dòng)編譯指令對(duì)應(yīng)的元素節(jié)點(diǎn):

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)前元素,這里第二個(gè)參數(shù)指定一個(gè)函數(shù),相當(dāng)于常用的link函數(shù) 
      // 當(dāng)然我們也可以指定一個(gè)對(duì)象,里面包含pre和post函數(shù),分別對(duì)應(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'; 
      }); 
    } 
  }; 
 });

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

以上是“Angular中如何實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)視圖”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

分享名稱:Angular中如何實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)視圖
網(wǎng)址分享:http://bm7419.com/article20/jdscco.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)定制網(wǎng)站、軟件開(kāi)發(fā)、面包屑導(dǎo)航、網(wǎng)站營(yíng)銷、手機(jī)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)