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 相关文章推荐
IE之动态添加DOM节点触发window.resize事件
Jul 27 Javascript
jquery滚动到顶部底部代码
Apr 20 Javascript
node.js+express制作网页计算器
Jan 17 Javascript
js中动态创建json,动态为json添加属性、属性值的实例
Dec 02 Javascript
jQuery.Form上传文件操作
Feb 05 Javascript
详解Vue-Cli 异步加载数据的一些注意点
Aug 12 Javascript
浅谈Angular4中常用管道
Sep 27 Javascript
JS基于for语句编写的九九乘法表示例
Jan 04 Javascript
vue将时间戳转换成自定义时间格式的方法
Mar 02 Javascript
layui select获取自定义属性方法
Aug 15 Javascript
详解微信小程序开发用户授权登陆
Apr 24 Javascript
js判断密码强度的方法
Mar 18 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
php防盗链的常用方法小结
2010/07/02 PHP
PHP字符串中特殊符号的过滤方法介绍
2014/02/18 PHP
php微信公众平台开发类实例
2015/04/01 PHP
微信支付PHP SDK之微信公众号支付代码详解
2015/12/09 PHP
CI框架(CodeIgniter)公共模型类定义与用法示例
2017/08/10 PHP
根据邮箱的域名跳转到相应的登录页面的代码
2012/02/27 Javascript
web性能优化之javascript性能调优
2012/12/28 Javascript
利用HTML5的画布Canvas实现刮刮卡效果
2015/09/06 Javascript
解决angular的post请求后SpringMVC后台接收不到参数值问题的方法
2015/12/10 Javascript
使用getBoundingClientRect方法实现简洁的sticky组件的方法
2016/03/22 Javascript
React Native 使用Fetch发送网络请求的示例代码
2017/12/02 Javascript
extract-text-webpack-plugin用法详解
2019/02/14 Javascript
layui将table转化表单显示的方法(即table.render转为表单展示)
2019/09/24 Javascript
webpack优化之代码分割与公共代码提取详解
2019/11/22 Javascript
js实现动态时钟
2020/03/12 Javascript
解决element-ui的下拉框有值却无法选中的情况
2020/11/07 Javascript
在elementui中Notification组件添加点击事件实例
2020/11/11 Javascript
浅谈es6中的元编程
2020/12/01 Javascript
[51:06]2018DOTA2亚洲邀请赛3月29日 小组赛A组 KG VS Liquid
2018/03/30 DOTA
在Python中使用SimpleParse模块进行解析的教程
2015/04/11 Python
Linux上安装Python的PIL和Pillow库处理图片的实例教程
2016/06/23 Python
Python 3 实现定义跨模块的全局变量和使用教程
2019/07/07 Python
浅析python 中大括号中括号小括号的区分
2019/07/29 Python
Python实现线性判别分析(LDA)的MATLAB方式
2019/12/09 Python
通过Python实现Payload分离免杀过程详解
2020/07/13 Python
Python调用高德API实现批量地址转经纬度并写入表格的功能
2021/01/12 Python
纯css3制作的火影忍者写轮眼开眼至轮回眼及进化过程实例
2014/11/11 HTML / CSS
JSP&Servlet技术面试题
2015/05/21 面试题
2014年教研活动总结范文
2014/04/26 职场文书
公司股东合作协议书
2014/09/14 职场文书
兵马俑的导游词
2015/02/02 职场文书
杭白菊导游词
2015/02/10 职场文书
停发工资证明范本
2015/06/12 职场文书
离婚财产分割协议书
2015/08/11 职场文书
电力培训学习心得体会
2016/01/11 职场文书
MySQL 聚合函数排序
2021/07/16 MySQL