이 기사에서 공유한 내용은 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
스크롤링 목록은 대형 화면 디스플레이 웹 앱에서 자주 사용됩니다. 여러 번 시도한 끝에 꽤 좋은 아이디어를 얻었습니다.
목록 헤더의 thead 부분은 고정된 반면 tbody 부분은 위쪽으로 스크롤됩니다.
본문 부분을 스크롤한 후 데이터를 새로 고쳐야 합니다. 최종 효과는 데이터베이스의 모든 관련 데이터를 위쪽 스크롤 형식으로 표시하는 것입니다.
p
를 table
의 외부 레이어에 컨테이너로 넣은 다음 table
이 top를 주기적으로 > 값으로 설정하고, <code>table
이 중간에 실행될 때까지 기다리고, 백엔드에서 데이터를 요청하고, tbody
구성 요소를 동적으로 생성하여 table
에 삽입합니다. code>를 선택한 다음 이전 tbody
가 사라지면(눈에 보이지 않게) 이 구성 요소를 삭제하세요. 아이디어는 실현 가능해 보였지만 실제로는 문제에 봉착했습니다. 이전 구성요소를 삭제하면 테이블
의 높이가 줄어들어 테이블이 즉시 무너집니다. 이것은 분명히 우리가 원하는 것이 아니며 부작용도 상당히 심각합니다. 드디어 퇴근길에 테이블 두 개가 필요 없는 방법이 생각났어요. 하나의 테이블
만 사용하여 정기적으로 이동하세요. 여행의 절반이 완료되면 타이머를 지우고 위치를 재설정하고 데이터의 절반을 업데이트하세요. 즉, 배열에 있는 데이터의 전반부가 제거되고, 배경에서 가져온 새로운 데이터가 배열에 접합됩니다. 이런 방식으로 데이터를 지속적으로 새로 고칠 수 있으며 테이블
이 계속해서 늘어나는 것처럼 보입니다. Code🎜url
만 전달하면 되며, 데이터 업데이트를 포함한 모든 작업은 구성요소 자체에서 완료됩니다. 이렇게 하면 구성 요소 캡슐화가 완료되고 재사용이 용이해집니다. 🎜🎜요약 및 생각🎜🎜1. 업데이트 데이터는 소스에서 업데이트해야 합니다. 즉, DOM 요소를 추가하거나 삭제하지 마십시오. 이 작업은 번거롭고 성능이 낮습니다. 소스에 넣는다는 것은 구성 요소 클래스에 표시 데이터를 저장하는 배열에 대해 소란을 피우는 것을 의미합니다. 🎜2. 백그라운드에서 요청된 새 데이터는 일찍 준비하여 다른 임시 배열에 배치해야 합니다. 캐시와 임시 레지스터에 해당합니다. 🎜3. 구성 요소를 함수로 상상합니다. 이 매개 변수가 하나만 있으면 구성 요소는 다른 값에 의존하지 않고 정상적으로 작동합니다. 느슨한 커플 링. 🎜4. 함수형 프로그래밍의 개념을 강화하세요. 이것이 React
의 특징이지만, Angular
도 사용할 수 있다는 느낌을 항상 받습니다. 🎜🎜관련 권장 사항: 🎜🎜🎜AngularJs 사용자 지정 지침 및 사용자 지정 지침의 명명 규칙을 설정하는 방법🎜🎜🎜🎜🎜AngularJs에서 모델, 컨트롤러(Controller) 및 뷰(View) 간의 관계는 무엇입니까? (사진 및 텍스트)🎜🎜🎜🎜위 내용은 Angular 6의 스크롤 목록 구성요소 캡슐화 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!