近两年当中使用Angular开发过很多项目,其中也涉及到一些树形结构视图的显示,最近的在项目中封装了大量的组件,一些组件也有树形结构的展示,所以写出来总结一下。
相信大家都知道,树结构最典型的例子就是目录结构了吧,一个目录可以包含很多子目录,子目录又可以包含若干个子孙目录,那咱们今天就以目录结构为例来说明一下Angular中树结构的实现。
首先,我们希望封装一个组件,用于显示整个目录的树形机构,代码如下:
<!DOCTYPE html> <html ng-app="treeDemo"> <body> <div ng-controller="TreeController"> <folder-tree current-folder="folder"></folder-tree> </div> <script src="/UploadFiles/2021-04-02/angular.min.js">就像上面的代码一样,我们直接声明folder-tree标签,将controller中的folder数据作为参数传递进去,预期会显示出一个完整的树状目录结构。接下来我们就来定义模块,控制器,以及相应的指令部分:
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的数据对象,包含整个的目录结构数据,接着定义了folderTree指令,它会使用tree.html作为模板进行视图渲染,我们这就来look look模板中的内容:
<p>{{currentFolder.name}}</p> <ul> <li ng-repeat="subfolder in currentFolder.children"> <folder-tree current-folder="subfolder"></folder-tree> </li> </ul>可以看到,在模板中有个很重要的环节,那就是使用ng-repeat指令遍历当前目录的子集,然后再次使用folder-tree组件来渲染相应的子目录,这种方式简直是完美,现在我们来看看渲染的结果:
这种在模板中嵌套使用指令的方法很完美,只可惜低版本的Angular中是无法实现的,会出现无限递归循环,造成页面假死,这是Angular本身的解析机制造成的。经测试,Angular 1.5.0及以上版本是没有问题的,但在Angular 1.4.9及以下版本中就会运行失败。假如你在项目中真的使用了低版本的Angular并且造成运行失败,我们还可以稍微改动一下模板,采用ng-include来实现同样的功能:
<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会创建一个独立的作用域,为了让其正确的引用到currentFolder变量,我们需要在每个ng-include中初始化currentFolder,将其赋值为ng-repeat中的当前subfolder,另外,别忘了ng-include指令中模板路径前后加上单引号。
这样确实可以,但是你可能觉得有些遗憾,没能使用最好的解决方案来实现这个树结构。
其实这个问题早就有人吐槽了,令人惊喜的是,有个叫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参数是对象类型link:{pre: function(...){}, post: function(...){}}则不做处理 // 如果link参数是函数类型则将其作为post-link函数在$compile之后调用 if(angular.isFunction(link)){ link = { post: link }; } // Break the recursion loop by removing the contents // 获取并清空当前元素的内容,后面进行编译 var contents = element.contents().remove(); var compiledContents; return { pre: (link && link.pre) "htmlcode">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方法编译指令当前元素,这里第二个参数指定一个函数,相当于常用的link函数 // 当然我们也可以指定一个对象,里面包含pre和post函数,分别对应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'; }); } }; });在上面代码中,我们在创建treeDemo模块时引入RecursionHelper模块,然后在创建folderTree指令时使用RecursionHelper服务,并且在compile方法中调用RecursionHelper的compile方法,即可修复上面的问题。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 【雨果唱片】中国管弦乐《鹿回头》WAV
- APM亚流新世代《一起冒险》[FLAC/分轨][106.77MB]
- 崔健《飞狗》律冻文化[WAV+CUE][1.1G]
- 罗志祥《舞状元 (Explicit)》[320K/MP3][66.77MB]
- 尤雅.1997-幽雅精粹2CD【南方】【WAV+CUE】
- 张惠妹.2007-STAR(引进版)【EMI百代】【WAV+CUE】
- 群星.2008-LOVE情歌集VOL.8【正东】【WAV+CUE】
- 罗志祥《舞状元 (Explicit)》[FLAC/分轨][360.76MB]
- Tank《我不伟大,至少我能改变我。》[320K/MP3][160.41MB]
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】