angular6的table组件开发的实现示例


Posted in Javascript onDecember 26, 2018

背景及吐槽:

今年有机会再次接触angualr这个框架,想起第一次接触ng还是16年读书的时候,当时还是ng1,然后学起来特别辛苦,学习曲线特别陡峭;而今年有一个项目重构直接采用了angular6,而后面该项目后面由我负责开发和维护,然后我又重新再学习了ng6,本以为有ng1的基础,学起来会好一些,然并卵,学习的曲线特别陡峭,但还是最后将ng6啃下来(很不情愿去学的,但没办法)。回归到项目,该项目没有引入其他组件库,所以很多基础组件都是自己开发(用ng开发那种酸爽很带劲),其中table组件让我思考了差不多两个星期,最后才开发出来,吐槽完毕,接下来就介绍一下我的做法,我的做法不一定最正确。

形式:

主要参考element里面的table组的格式:

vue:

<el-table :data="tableData">
  <el-table-column prop="date" label="日期"></el-table-column>
  <el-table-column label="操作">
   <template slot-scope="scope">
    <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
   </template>
  </el-table-column>
 </el-table>

所以得到了angualr的table组件的格式:

<app-widget-table [data]="tableData">
  <app-widget-table-column prop="date" label="日期"></app-widget-table-column>

  <app-widget-table-column label="操作">
   <ng-template #scope let-row="scope">
      <ng-widget-button (click)="handleClick(row)" type="text" size="small">查看</el-button>
   </ng-template>
  </app-widget-table-column>
</app-widget-table>

在angular的table组件中,最为困难就是ng-template如何将作用域绑定到ng-widget-button组件中;

关键点知识讲解:

ng-content:
可以将父组件中所包含的所有子组件,都插入table组件中ng-container所在的位置,跟vue中的slot很像;

ng-container:
可以作为一个组件的模板,跟vue里面的template组件很像;

ng-template:
该东西,是整个组件中最为麻烦的一个东西,直接使用它,会没有任何效果,必须要和TemplateRef和ngTemplateOutlet一起使用,才有有效果,主要是作为模板并引入作用域,具体原理可以看一下官方文档(https://www.angular.cn/api)

TemplateRef:
主要是用来获取ng-template组件的引用;

ngTemplateOutlet:
将ng-template的内容在html页面展示出来,并绑定变量,就像vue中的router-view;

QueryList:
获取table组件中所有的内容指引;

ContentChildren:
内容映射的接口,针对多个子元素采用

ContentChild:
内容映射的接口,针对单个子元素采用

先对app-widget-table-column组件进行分析:
该组件的作用就是为了运输数据,并且引入内容,该组件本身是不会有任何操作和逻辑,就是一个运输工;

table-column.component.html:

<ng-container></ng-container>

table-column.component.ts:

import {Component, Input, Output, TemplateRef, ContentChild, AfterContentInit} from '@angular/core';

@Component({
  selector: 'app-widget-table-column',
  templateUrl: './table-column.component.html',
  styleUrls: ['./table-column.component.less'],
  preserveWhitespaces: false
})
export class TableColumnComponent implements AfterContentInit {
  constructor() {

  }

  @Input()
  label: string;

  @Input()
  prop: string;

  @Input()
  class: string;

  @Input()
  style: object;

  @ContentChild('scope') // 获取ng-template组件的一个本地变量,并修饰scope对象
  scope: TemplateRef<any>; // 获取ng-template的指引,主要是其内容,any表示该指可以是任何内容

  ngAfterContentInit(): void {}
}

table.component.html

<div>
  <div>
    <ng-content></ng-content> // 主要是用来引入整个table组件的内容,但不会在页面显示任何内容
  </div>

  <table class="table">
    <thead>
    <tr>
     <th *ngFor="let label of labelList">{{label}}</th>  // 类似于v-for,主要讲table-cloumn的所有label搜集,并展示
    </tr>
    </thead>

    <tbody *ngIf="data.length > 0">
    <ng-container *ngFor="let item of data; let i = index">
      <tr>
        <ng-container *ngFor="let row of tableColumn['_results']">
          <td *ngIf="row.prop" [ngStyle]="row.style" [ngClass]="row.class">{{item[row.prop]}}</td> // 直接展示

          <td *ngIf="row.scope" [ngStyle]="row.style" [ngClass]="row.class">
            <ng-container *ngTemplateOutlet="row.scope; context: {$implicit: {}, scope: data[i]}">
            </ng-container> // 展示ng-template的内容
          </td>
        </ng-container>
      </tr>
    </ng-container>
    </tbody>
  </table>

  <div *ngIf="data.length === 0" class="none-data">暂无数据!</div>
</div>

table.component.ts:

import {Component, OnInit, Input, Output, ContentChildren, AfterContentInit, ViewChild, AfterViewInit, QueryList} from '@angular/core';
import {TableColumnComponent} from '../table-column/table-column.component';

@Component({
  selector: 'app-widget-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.less'],
  preserveWhitespaces: false
})
export class TableComponent implements OnInit, AfterContentInit {
  constructor() {

  }

  @ContentChildren(TableColumnComponent)
  tableColumn: QueryList<TableColumnComponent>; // 获取table-cloumn组件的所有实例

  @Input()
  data: object[];

  labelList: string[] = [];

  ngOnInit(): void {
    if (!(this.data instanceof Array)) {
      throw new Error('the data into TableComonent must be Array!');
    }
  }

  ngAfterContentInit(): void {
    this.labelList = this.tableColumn['_results'].map(item => item.label);
  }
}

虽然看起来这两个组件的代码不多,但里面的逻辑却比较绕,这也证明了ng用起来十分难上手,不过真的称赞的是,ng采用ts和rx,用上手确实是比较爽。

这两个组件目前还是比较粗糙,功能和特性也不是特别多,只能满足一般表格的需求,后续会继续完善该组件以及其他项目中用ng来开发的基础组件,希望能沉淀出一套ng的组件库。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js验证表单第二部分
Nov 25 Javascript
向fckeditor编辑器插入指定代码的方法
May 25 Javascript
Angular用来控制元素的展示与否的原生指令介绍
Jan 07 Javascript
javascript实现简易计算器的代码
May 31 Javascript
基于KO+BootStrap+MVC实现的分页控件代码分享
Nov 07 Javascript
vue.js组件vue-waterfall-easy实现瀑布流效果
Aug 22 Javascript
vue-router history模式下的微信分享小结
Jul 05 Javascript
jquery ajax加载数据前台渲染方式 不用for遍历的方法
Aug 09 jQuery
vue-rx的初步使用教程
Sep 21 Javascript
vue组件从开发到发布的实现步骤
Nov 11 Javascript
js实现延迟加载的几种方法详解
Jan 19 Javascript
js根据后缀判断文件文件类型的代码
May 09 Javascript
详解VUE里子组件如何获取父组件动态变化的值
Dec 26 #Javascript
JavaScript基础之静态方法和实例方法分析
Dec 26 #Javascript
微信小程序实现文字跑马灯
May 26 #Javascript
基于JavaScript canvas绘制贝塞尔曲线
Dec 25 #Javascript
基于js Canvas实现二次贝塞尔曲线
Dec 25 #Javascript
JavaScript实现小球沿正弦曲线运动
Sep 07 #Javascript
微信小程序使用二次贝塞尔曲线画波浪
Dec 25 #Javascript
You might like
在任意字符集下正常显示网页的方法二(续)
2007/04/01 PHP
php中用date函数获取当前时间有误的解决办法
2013/08/02 PHP
kohana框架上传文件验证规则写法示例
2014/07/14 PHP
浅析PHP数据导出知识点
2018/02/17 PHP
PHP实现打包zip并下载功能
2018/06/12 PHP
Laravel 实现Controller向blade前台模板赋值的四种方式小结
2019/10/22 PHP
jQuery实现切换页面过渡动画效果
2015/10/29 Javascript
使用getBoundingClientRect方法实现简洁的sticky组件的方法
2016/03/22 Javascript
Bootstarp 基础教程之表单部分实例代码
2017/02/03 Javascript
js canvas实现擦除效果示例代码
2017/04/26 Javascript
微信小程序分页加载的实例代码
2017/07/11 Javascript
vue.js移动端app之上拉加载以及下拉刷新实战
2017/09/11 Javascript
jquery实现侧边栏左右伸缩效果的示例
2017/12/19 jQuery
JavaScript选择排序算法原理与实现方法示例
2018/08/06 Javascript
小试SVG之新手小白入门教程
2019/01/08 Javascript
详释JavaScript执行环境与执行栈
2019/04/02 Javascript
vue实现手机端省市区区域选择
2019/09/27 Javascript
如何优雅地取消 JavaScript 异步任务
2020/03/22 Javascript
JS原形与原型链深入详解
2020/05/09 Javascript
VueX模块的具体使用(小白教程)
2020/06/05 Javascript
[02:36]DOTA2英雄基础教程 帕格纳
2014/01/20 DOTA
[16:21]教你分分钟做大人:圣堂刺客
2014/12/03 DOTA
[56:13]DOTA2-DPC中国联赛定级赛 LBZS vs Phoenix BO3第一场 1月10日
2021/03/11 DOTA
python文件与目录操作实例详解
2016/02/22 Python
python实现FTP服务器服务的方法
2017/04/11 Python
python列表生成式与列表生成器的使用
2018/02/23 Python
Python测试网络连通性示例【基于ping】
2018/08/03 Python
在pycharm上mongodb配置及可视化设置方法
2018/11/30 Python
python3+selenium自动化测试框架详解
2019/03/17 Python
详解python函数的闭包问题(内部函数与外部函数详述)
2019/05/17 Python
django框架cookie和session用法实例详解
2019/12/10 Python
pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)
2020/06/24 Python
FC-Moto英国:欧洲最大的摩托车服装和头盔商店之一
2019/08/25 全球购物
2013的个人自我评价
2013/12/26 职场文书
优秀党员先进材料
2014/12/18 职场文书
SQL 聚合、分组和排序
2021/11/11 MySQL