這篇文章給大家分享的內容是關於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
看起來是一直往上走的。
<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>
import { 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); } }
.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中滾動列表組件的封裝的分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!