Angular公共组件的开发

Angular公共组件开发

小谈一下:

最近在国外的一些社区和网站上经常看到一个技术发展方向Bit,国外预测前端2020年的发展方向是组件公共化,大家可以上传自己开发的组件到bit,也可以直接下载复用别人的组件,并且无论组件是用Vue、Ng还是React开发的,都会被打包成一个js文件,直接在index.html导入即可实现复用,看似很神奇的一个东西,但是大量导入外部组件,一旦出错,维护成本将大大增加,开发者都清楚,修bug比写bug更累心,况且还是格式化过的代码...总之,目前bit上的资源数量和可利用量都很低,可能是大家还没有适应这种开发模式,或者是其他一些原因...下面我就Angular8,谈一下怎么在项目中开发并使用公共组件吧。

重点知识点:

@Input() @Output() @Viewchild() @ContentChild()这些装饰器还熟悉吗?
不熟悉也没关系,只看概念真的能把人绕晕,还是实战让人理解地更快。所用到的也就是通过这些装饰器进行父子组件之间的通讯。记得vue这一块用的也是类似的方法,具体就不展开说了。先说一下这几个装饰器的作用吧。
以上装饰器是Angular的内置装饰器,也就是框架自带,初设的,不用我们再自己封装。

@Input 

比如: @Input() dataSource: any;
定义在公共组件里,用来接收所调用者通过属性绑定传来的值,在公共组件OnInit里才能接收到。之后就可以当成变量用,但是是双向的,在公共组件里修改其值之后,调用者那边的值也随之改变,因此最好不要直接修改这个变量,先复制一份,去修改复制过的,保留元数据的clean。

@Output 

比如:@Output() readonly sort: EventEmitter; 
定义在公共组件里,用来导出在公共组件里触发的事件并导出参数。定义之后需要在构造器里先初始化一下
this.sort = new EventEmitter(); 
之后在所触发的事件中通过this.sort.emit(data);,传出参数数据。

@ContentChild 

比如: @ContentChild(TemplateRef, { static: true }) tableActions: TemplateRef;
定义在公共组件里,用来接收调用者传入的template。这里需要在html里留出一个供template渲染的块

tableActions是template的Name,context是传出的数据; 
调用时
在这里面写入你想在公共组件里#tableActions位置插入的HTML标签。

下面提供一下源码:

公共组件 table.component.ts

import {
    Component,
    OnInit,
    Input,
    Output,
    EventEmitter,
    TemplateRef,
    ContentChild,
    SimpleChanges,
    OnChanges
} from '@angular/core';
import { SelectionModel } from '@angular/cdk/collections';
import { MatDialog } from '@angular/material/dialog';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { MatTableDataSource } from '@angular/material/table';

export interface TableColumns {
    field: string; // 字段
    title: string; // 字段名
    isShow?: boolean; // 是否显示
    isSort?: boolean; // 可否排序
    type?: ColumnType; // 类型
}
export enum ColumnType {
    default, // 默认
    slideToggle // slide滑动条
}

@Component({
    selector: 'table',
    templateUrl: './table.component.html',
    styleUrls: ['./table.component.scss']
})
export class TableComponent implements OnInit, OnChanges {
    selectionRow = new SelectionModel(true, []); // 选中的行
    columnType: typeof ColumnType = ColumnType; // 定义Column类型枚举
    renderedDataSource: any; // 转化后的数据
    @Input() dataSource: any; // 远程数据
    @Input() placeholder: string; // // 默认提示
    @Input() checkable: boolean; // // 是否出现复选框
    @Input() hiddenCheckHead: boolean; // // 是否隐藏复选框title
    @Input() columns: TableColumns[]; // 远程列名
    @Output() readonly checkChange: EventEmitter; // 复选框点击事件传出选中元素
    @Output() readonly sort: EventEmitter; // 复选框点击事件传出选中元素
    @ContentChild(TemplateRef, { static: true }) tableActions: TemplateRef; // 子组件的模板

    constructor(public dialog: MatDialog, public httpClient: HttpClient) {
        this.checkChange = new EventEmitter();
        this.sort = new EventEmitter();
        this.checkable = false;
        this.placeholder = '抱歉!没有搜索到任何结果';
        this.columns = [];
        this.renderedDataSource = new MatTableDataSource([]);
        this.hiddenCheckHead = true;
    }

    /**
     * when data change trigger
     * @param changes changed data
     */
    ngOnChanges(changes: SimpleChanges): any {
        if (changes['dataSource']) {
            this.renderedDataSource = new MatTableDataSource(this.dataSource);
        }
    }
    /**
     * init the columns
     */
    ngOnInit(): any {
        this.columns.forEach((v, i, arr) => {
            if (!v.isShow) {
                arr.splice(i, 1);
                this.columns = arr;
            }
        });
        if (this.tableActions) {
            this.columns.push({
                field: 'actions',
                title: '操作',
                isShow: true,
                isSort: false,
                type: ColumnType.default
            });
        }
        if (this.checkable) {
            this.columns.unshift({
                field: 'check',
                title: '选择',
                isShow: true,
                isSort: false,
                type: ColumnType.default
            });
        }
    }
    /**
     * Whether the number of selected elements matches the total number of rows.
     */
    isAllSelected(): any {
        const numSelected = this.selectionRow.selected.length;
        const numRows = this.renderedDataSource.data.length;
        return numSelected === numRows;
    }
    /**
     * Selects all rows if they are not all selected; otherwise clear selection.
     */
    masterToggle(): any {
        this.isAllSelected()
            ? this.selectionRow.clear()
            : this.renderedDataSource.data.forEach((row: any) => {
                  this.selectionRow.select(row);
              });
    }
    /**
     * click single row and output the event
     * @param row checked row
     */
    checkChanged(row?: any): any {
        this.checkChange.emit(this.selectionRow.selected);
    }
    /**
     * The label for the checkbox on the passed row
     * @param row checked data
     */
    checkboxLabel(row?: any): string {
        if (!row) {
            return `${this.isAllSelected() ? 'select' : 'deselect'} all`;
        } else {
            return `${
                this.selectionRow.isSelected(row) ? 'deselect' : 'select'
            } row ${row.ID + 1}`;
        }
    }

    sorted(data: any): any {
        this.sort.emit(data);
    }
}


table.component.html

{{ col.title }} {{ row[col.field] }}

### 调用时:

call.component.html


                
          

call.component.ts (部分代码)


    tableDatasource: any; // table数据 
    tableColumns: TableColumns[]; // table column
    checkable: boolean;
    
    ----------
    
    checkChanged(data: any){
        console.log(data);
    }
    onSorted(data: any){
        console.log(data)
    }

好了,到这一个公共表格就开发完成了。有问题欢迎共同探讨。

你可能感兴趣的:(Angular)