您好,欢迎访问一九零五行业门户网

对Angular 6中滚动列表组件的封装的分析

这篇文章给大家分享的内容是关于对angular 6中滚动列表组件的封装的分析,有一定的参考价值,有需要的朋友可以参考一下。
前言学习应为input和output相结合之过程,这就是写这篇文章的原因。
在大屏幕展示web app中,经常会用到滚动列表。经过几次尝试,确定了一个还不错的思路。
需求列表表头thead部分静止,而tbody部分向上滚动。
tbody部分滚动结束之后,需要刷新数据,最终效果是以向上滚动的形式将数据库中全部相关数据展示出来。
分析如果数据量比较小的话,我们完全可以将数据一次性全部拿出来,放到dom中进行循环滚动。实际就是类似轮播图的效果。
但若有很多数据的话,这样做很可能造成内存泄露。自然,我们可以想到将列表数据分页。我最初的想法是,在table的外层放一个p作为容器,然后table定时向上增加top值,等table跑了一半时,向后端请求数据,动态创建一个组件tbody插入到table中,然后等前面一个tbody走完时(看不见了),将这个组件删除。该想法看起来可行的,但是实践中遇到了不少麻烦。在删除前面的组件时,会导致table的高度减小,表格瞬间掉下去了。这显然不是我们想要的,副作用挺大的。
既然这样,我把tbody分开到两个table里,两个table循环。当前一个table下面没有数据时,第二个table开始走,等第一个table完全走出p,将它位置重置到p的下面,并更新数据,然后重复之间的动作。完成起来稍微有点麻烦,不过效果还说得过去,差强人意。问题是,两个定时器不稳定,打开其他软件,再回来时,两个table跑的不一致了。这个先天性疾病,setinterval就是不够精确的,两个定时器一起容易出现配合不好的情况。
最终,在下班回家的路上,我想到了一个不需要两个table的方法。只用一个table定时上移,走完一半时,清除定时器,重置位置,并更新一半的数据。也就是去除数组中前一半数据,将后台拉过来的新数据拼接在数组上。这样就可以实现数据的持续刷新,并且table看起来是一直往上走的。
代码scroll-table.component.html<p class="table-container">  <table class="head-show">    <thead>      <tr>        <th style="width:12.8%;">字段1</th>        <th style="width:12.8%;">字段2</th>        <th>字段3</th>        <th style="width:12.8%;">字段4</th>      </tr>    </thead>  </table>  <p class="scroller-container">    <table #scroller class="scroller">      <tbody>        <tr *ngfor="let ele of tbody">          <td style="width:12.8%;">{{ele.field01}}</td>          <td style="width:12.8%;">{{ele.field02}}</td>          <td><p>{{ele.field03}}</p></td>          <td style="width:12.8%;">{{ele.field04}}</td>        </tr>      </tbody>    </table>  </p></p>
scroll-table.component.tsimport { component, oninit, viewchild, elementref, input } from '@angular/core';import { httpservice } from '../http.service';@component({  selector: 'app-scroll-table',  templateurl: './scroll-table.component.html',  styleurls: ['./scroll-table.component.scss']})export class scrolltablecomponent implements oninit {  tbody: any = [];  @input() url; //将地址变成组件的一个参数,也就是输入属性  //控制滚动的元素  @viewchild('scroller') scrollerref: elementref;  timer: any;  freshdata: any;  pagenow = 1;//pagenow是当前数据的页码,初始化为1  constructor(private http: httpservice) {}  ngoninit() {    //初始化拿到native    let scroller: htmlelement = this.scrollerref.nativeelement;    this.http.sendrequest(this.url).subscribe((data :any[]) => {            this.tbody = data.concat(data);    });    //开启定时器    this.timer = this.go(scroller);  }  getfreshdata() {  //每次请求数据时,pagenow自增1    this.http.sendrequest(`${this.url}?pagenow=${++this.pagenow}`).subscribe((data:any[]) => {      if(data.length<10) { //数据丢弃,pagenow重置为1 this.pagenow = 1; } this.freshdata = data; }); } go(scroller) { var moved = 0, step = -50, timer = null, task = () => {        let style = document.defaultview.getcomputedstyle(scroller, null);        let top = parseint(style.top, 10);        if (moved < 10) {          if(moved===0) {            this.getfreshdata();          }          scroller.style.transition = top 0.5s ease;          moved++;          scroller.style.top = top + step + 'px';        } else {          //重置top,moved,清除定时器          clearinterval(timer);          moved = 0;          scroller.style.transition = none;          scroller.style.top = '0px';          //更新数据          this.tbody = this.tbody.slice(10).concat(this.freshdata);          timer = setinterval(task,1000);        }      };    timer = setinterval(task, 1000);  }}
scroll-table.component.scss.table-container {    width: 100%;    height: 100%;}.head-show {    border-top: 1px solid #4076b9;    height: 11.7%;}.scroller-container {    border-bottom: 1px solid #4076b9;    //border: 1px solid #fff;    width: 100%;    //height: 88.3%;    height: 250px;    box-sizing: border-box;    overflow: hidden;    position:relative;    .scroller {        position: absolute;        top:0;        left:0;        transition: top .5s ease;    }}table {    width: 100%;    border-collapse: collapse;    table-layout: fixed;    //border-bottom:1px solid #4076b9;    th {                border-bottom:1px dashed #2d4f85;        color:#10adda;        padding:8px 2px;        font-size: 14px;    }    td {        border-bottom: 1px dashed #2d4f85;        font-size: 12px;                color:#10adda;        position: relative;        height: 49px;        p{            padding:0 2px;            box-sizing: border-box;            text-align:center;            display: table-cell;            overflow: hidden;            vertical-align: middle;        }        //border-width:1px 0 ;    }}
这样实现的效果是,该组件只需要传入一个参数url,然后所有的操作、包括更新数据,全部由组件自身完成。从而完成了组件的封装,便于复用。
总结和思考1、更新数据应该放在源头更新,也就是说,不要去添加和删除dom元素,这样操作麻烦,性能也低。放在源头的意思是,在组件类中存储展示数据的那个数组上做文章。
2、后台请求新数据应该提早准备就绪,放在另一个临时数组中。它相当于一个缓存,一个暂存器。
3、我将组件想象成一个函数,它只有一个参数,就是数据的地址,只要有这个参数,组件就能正常工作,不依赖于其他任何值。松耦合性。
4、加强函数式编程思想,虽然这是react的特色,但我总觉得angular也可以的。
相关推荐:
angularjs自定义指令可以如何来设置以及自定义指令的命名规范
angularjs中model、controller(控制器)和view(视图)之间有什么样的关系?(图文)
以上就是对angular 6中滚动列表组件的封装的分析的详细内容。
其它类似信息

推荐信息