Angular树组件开发

2021-03-28 10:37:16 浏览数 (1)

完成的效果:

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

树组件的目录结构:

目录结构目录结构

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

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中成功输出了选择的节点信息

0 人点赞