前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Angular树组件开发

Angular树组件开发

原创
作者头像
4cos90
修改2021-03-28 10:37:16
1.3K0
修改2021-03-28 10:37:16
举报
文章被收录于专栏:随想随想

完成的效果:

数据树结构展示,其中包含子节点的节点可通过点击文字展开或隐藏其子节点,每个节点可点击勾选框勾选
数据树结构展示,其中包含子节点的节点可通过点击文字展开或隐藏其子节点,每个节点可点击勾选框勾选

树组件的目录结构:

目录结构
目录结构

树组件的结构非常简单,仅需要一个组件即可完成。

Tree组件:

先放下代码:

代码语言:javascript
复制
<div class="TreeBase">
    <div class="TreeNode">
        <div [class]="'NodeSelect' +  ' NodeSelect_' + (TreeData[DefaultConfig.Select] || false)" (click)="SelectClick(TreeData)"></div>
        <div class="NodeName Cursor ExWidth" (click)="ExplandClick(TreeData)">
            <span class="Span NameSpan" [title]="TreeData[DefaultConfig.Name]">{{ TreeData[DefaultConfig.Name] }}</span>
        </div>
        <div *ngIf="TreeData[DefaultConfig.Member] && TreeData[DefaultConfig.Member].length > 0">
            <div [class]="'NodeExpland NodeExpland_' + (TreeData[DefaultConfig.Expland] || false)"></div>
        </div>
    </div>
    <div *ngIf="TreeData[DefaultConfig.Member] && TreeData[DefaultConfig.Member].length > 0 && TreeData[DefaultConfig.Expland]" class="ChildNode">
        <div *ngFor="let MemberData of TreeData[DefaultConfig.Member]">
            <app-Tree [TreeData]="MemberData" (NodeClickEvent)="NodeClickEventEmit($event)" [Name]="DefaultConfig.Name" [Code]="DefaultConfig.Code"></app-Tree>
        </div>
    </div>
</div>
代码语言:javascript
复制
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';


@Component({
    selector: 'app-Tree',
    templateUrl: './Tree.component.html',
    styleUrls: ['./Tree.component.css']
})
export class TreeComponent implements OnInit {

    DefaultConfig: any;

    @Input() TreeData: any;
    @Input() Name: string;
    @Input() Code: string;
    @Input() Member: string;

    @Output() NodeClickEvent = new EventEmitter<any>();

    constructor(

    ) { }

    ngOnInit() {
        this.DefaultConfig = {
            Name: this.Name || "Name",
            Code: this.Code || "Code",
            Member: this.Member || "Member",
            Select: "Select",
            Expland: "Expland",
        }
    }

    ExplandClick(event: any) {
        if (event[this.DefaultConfig.Member] && event[this.DefaultConfig.Member].length > 0) {
            event[this.DefaultConfig.Expland] = !(event[this.DefaultConfig.Expland] || false);
        }
    }

    SelectClick(event: any) {
        event[this.DefaultConfig.Select] = !event[this.DefaultConfig.Select];
        this.NodeClickEvent.emit(event);
    }

    NodeClickEventEmit(event: any) {
        this.NodeClickEvent.emit(event);
    }
} 
代码语言:javascript
复制
.TreeBase {
    width: 100%;
    float: right;
}

.TreeNode {
    height: 33px;
    width: 100%;
}

.NodeSelect {
    float: left;
    height: 16px;
    width: 16px;
    margin-left: 7px;
    margin-top: 8px;
    margin-right: 7px;
}

.NodeSelect_true {
    cursor: pointer;
    background: url('./Resource/Icon-select.png') no-repeat center center;
}

.NodeSelect_false {
    cursor: pointer;
    background: url('./Resource/Icon-unselect.png') no-repeat center center;
}

.NodeName {
    float: left;
    margin-top: 5px;
    height: 22px;
}

.ExWidth {
    width: calc(100% - 54px);
}

.Width {
    width: calc(100% - 40px);
}

.Cursor {
    cursor: pointer;
}

.NodeExpland {
    float: left;
    width: 16px;
    height: 16px;
    margin-top: 8px;
    margin-left: 4px;
    margin-right: 4px;
}

.NodeExpland_true {
    background: url('./Resource/Explanded.png') no-repeat center center;
}

.NodeExpland_false {
    background: url('./Resource/Expland.png') no-repeat center center;
}

.Span {
    font-family: PingFang SC Regular;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
    display: block;
    user-select: none;
}

.NameSpan {
    font-size: 16px;
    height: 22px;
    color: rgba(255, 255, 255, 1);
}

.ChildNode {
    float: right;
    width: 90%;
}

首先要注意的是this.DefaultConfig这个配置。一般来说,展示数据需要两个属性:Name和Code,Name是该节点在界面上展示的文字,他是可以重复的,展示的时候也会考虑添加一些符合用户阅读习惯的信息。Code是该节点的主键,即是使用树组件时判断选中了哪个节点的唯一标识。开发过程中,使用的数据结构并不一定恰好是Name和Code,因此允许开发者指定自己数据结构中对应功能的属性名。Member是该节点的子节点列表。同样我们允许开发者指定属性名。TreeData是用户需要展示的数据。

观察html中包含两个部分。

class=“TreeNode”中实现了传入节点本身的样式。

class=“ChildNode”中为每个子节点递归调用了树组件。同样注意要把用户指定的参数名继续传递下去。

注意NodeClickEvent在递归调用树组件时,内部的节点被点击时,点击事件会一层一层的传递到最外层。

在其他页面使用树组件:

代码语言:javascript
复制
    <div style="height: 500px;width: 300px;background: rgba(29, 51, 76, 1);">
        <app-Tree [TreeData]="TreeData" (NodeClickEvent)="NodeClickEventEmit($event)" [Name]="'Name'" [Code]="'Code'" [Member]="'Member'"></app-Tree>
    </div>
代码语言:javascript
复制
import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'app-index',
    templateUrl: './index.component.html',
    styleUrls: ['./index.component.css']
})
export class IndexComponent implements OnInit {
    TreeData = {
        Name: "学校",
        Code: "School",
        Member: [
            {
                Name: "高二一班", Code: "C21", Member: [
                    { Name: "小明", Code: "S01" },
                    { Name: "小红", Code: "S02" },
                    { Name: "小刚", Code: "S03" },
                ]
            }, {
                Name: "高二二班", Code: "C21", Member: [
                    { Name: "大明", Code: "S04" },
                    { Name: "大红", Code: "S05" },
                    { Name: "大刚", Code: "S06" },
                ]
            },
            { Name: "高二三班", Code: "C21" },
            { Name: "高二四班", Code: "C21" },
        ]
    }
    
    ngOnInit() {

    }
    
    NodeClickEventEmit(event: any) {
        console.log("SelectNode-->", event);
    }
}

模拟了一个学校-班级-学生的树结构数据。

在appmodule中引入树组件
在appmodule中引入树组件

这样一个简单的树组件就封装完成了!

点击Select按钮,在index中成功输出了选择的节点信息
点击Select按钮,在index中成功输出了选择的节点信息

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档