为了方便, 本文全部的Angular
均表示Angula2及以上版本,对于使用Angular1
/Angular.js
的读者可做为参考html
目前正在写一个Angular
的Markdown
编辑器,须要一个树形组件来写文件系统。恰好以前用过Angular Material
的树形组件,就想照着写一个。毕竟直接把Angular Material
引进来会多出其余用不到的组件,并且本身实现还能更深刻学习Angular
。node
在写以前我百度了一通,发现大部分文章的Tree组件实现都是把节点模板直接写在了组件里,相似下面git
<!--Tree组件--> <tree> <tree-node></tree-node> </tree> <!--TreeNode组件--> <tree-node> <!--本节点内容--> {{ nodeName }} <!--子节点--> <tree-node *ngIf="hasChildren"> </tree-node> <tree-node>
说明一下: Tree
组件里面包含TreeNode
组件,TreeNode
组件内部实现了递归子节点的逻辑。
其实这样的结构已经足够知足个人需求了,可是(由于强迫症)这样的可重用性几乎是没有,由于节点的内容已经写死在TreeNode
组件里了。
而后我想到了Angular Material
的CdkTree
。他的结构以下github
<tree dataSource="ds"> <tree-node> <!--本节点内容--> {{ nodeName }} <!--子节点出口--> <outlet></outlet> </tree-node> </tree>
说明: 简单的说就是CdkTree
把<tree-node>
里的内容做为一个模板保存起来,而后根据数据源递归渲染出来。这样咱们就能够在不修改Tree
和TreeNode
组件前提下改变其内容。markdown
在实现以前须要理解Angular
的几个装饰器,学过Angular
的应该都不会陌生。编辑器
@ViewChild
- 在视图中查询匹配的第一个元素@ViewChildren
- 在视图中查询匹配的全部元素@ContentChild
- 在组件标签包裹的内容中查询匹配的第一个元素@ContentChildren
- 在组件标签包裹的内容中查询匹配的全部元素View和Content的区别
View: 在组件的模板中定义的内容,即咱们手动写在xxx.component.html里的内容
Content: 在Host
元素的<opening>
和<closeing>
标签中的内容学习
在Tree组件中有四个比较重要的类spa
@Component: TreeComponent
@Component: TreeNodeComponent
@Directive: TreeNodeOutletDirective
@Directive: TreeNodeDefDirective
该组件就是咱们要是实现的Tree
组件,用于包裹TreeNode
code
树节点组件,咱们自定义的模板就写在这里面component
这个指令设置了子节点的出口位置
这个指令用来定义树节点所需的数据,即咱们使用这个指令让模板可使用每一个树节点对应的数据
咱们先看一下完成后的样子
<nb-tree [dataSource]="fileTree"> <nb-tree-node *nbTreeNodeDef="let data = data"> <li> <span>{{ data.title }}</span> </li> <ul> <ng-container nbTreeNodeOutlet></ng-container> </ul> </nb-tree-node> </nb-tree>
(标签前面的nb请忽略,这只是默认的前缀)上面是完成后的简易版。
咱们能够看到在tree
组件上设置了dataSource
。
而后在treeNodeDef
指令中咱们导出了数据对象data
。而后在模板中使用了它<span>{{ data.title }}</span>
。
最后咱们在<ng-container>
上用treeNodeOutlet
指令设置了子节点的出口。
懒得详细写实习了。。。有空再写吧。本文主要提供一个通用树形组件的思路。
想看代码的,看结尾。有一个不是很完善的tree
组件,我用在正在写的Markdown编辑器上了。
Github: tree
组件连接