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 相关文章推荐
Javascript调用XML制作连动下拉列表框
Jun 25 Javascript
爱恋千雪-US-AscII加密解密工具(网页加密)下载
Jun 06 Javascript
js弹出层包含flash 不能关闭隐藏的2种处理方法
Jun 17 Javascript
js模拟C#中List的简单实例
Mar 06 Javascript
IE6已终止操作问题的2种情况及解决
Apr 23 Javascript
jQuery使用removeClass方法删除元素指定Class的方法
Mar 26 Javascript
javascript实现框架高度随内容改变的方法
Jul 23 Javascript
JS中递归函数
Jun 17 Javascript
javascript中关于类型判断的一些疑惑小结
Oct 14 Javascript
微信小程序实现的一键复制功能示例
Apr 24 Javascript
微信小程序实现点击卡片 翻转效果
Sep 04 Javascript
详解React路由传参方法汇总记录
Nov 29 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
利用递归把多维数组转为一维数组的函数
2006/10/09 PHP
连接到txt文本的超链接,不直接打开而是点击后下载的处理方法
2009/07/01 PHP
浅谈web上存漏洞及原理分析、防范方法(安全文件上存方法)
2013/06/29 PHP
Yii中实现处理前后台登录的新方法
2015/12/28 PHP
PHP微信公众号开发之微信红包实现方法分析
2017/07/14 PHP
TBCompressor js代码压缩
2011/01/05 Javascript
Easy.Ajax 部分源代码 支持文件上传功能, 兼容所有主流浏览器
2011/02/24 Javascript
基于js disabled=&quot;false&quot;不起作用的解决办法
2013/06/26 Javascript
document.getElementBy(&quot;id&quot;)与$(&quot;#id&quot;)有什么区别
2013/09/22 Javascript
jQuery插件scroll实现无缝滚动效果
2015/04/27 Javascript
js控制TR的显示隐藏
2016/03/04 Javascript
使用JavaScript判断手机浏览器是横屏还是竖屏问题
2016/08/02 Javascript
js返回顶部实例分享
2016/12/21 Javascript
bootstrap modal+gridview实现弹出框效果
2017/08/15 Javascript
jQuery图片缩放插件smartZoom使用实例详解
2017/08/25 jQuery
JS实现点击链接切换显示隐藏内容的方法
2017/10/19 Javascript
Vuex中mutations与actions的区别详解
2018/03/01 Javascript
基于iScroll实现内容滚动效果
2018/03/21 Javascript
js 实现 list转换成tree的方法示例(数组到树)
2019/08/18 Javascript
JavaScript find()方法及返回数据实例
2020/04/30 Javascript
在react项目中使用antd的form组件,动态设置input框的值
2020/10/24 Javascript
[47:36]Optic vs Newbee 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
Python3中类、模块、错误与异常、文件的简易教程
2017/11/20 Python
Django 生成登陆验证码代码分享
2017/12/12 Python
使用pandas的DataFrame的plot方法绘制图像的实例
2018/05/24 Python
详解PANDAS 数据合并与重塑(join/merge篇)
2019/07/09 Python
python lambda表达式(匿名函数)写法解析
2019/09/16 Python
Python自动化办公Excel模块openpyxl原理及用法解析
2020/11/05 Python
详解appium自动化测试工具(monitor、uiautomatorviewer)
2021/01/27 Python
详解CSS3的图层阴影和文字阴影效果使用
2016/06/09 HTML / CSS
美国顶级户外凉鞋品牌:Chacos
2017/03/27 全球购物
医学检验专业个人求职信范文
2013/12/04 职场文书
军训拉歌口号
2014/06/13 职场文书
小学生我的梦想演讲稿
2014/08/21 职场文书
学生保证书格式
2015/02/27 职场文书
JavaScript实现音乐播放器
2022/08/14 Javascript