背景:公司前端開發一直使用angular,后公司想開發移動app應用,便考慮使用Ionic+angular使用。項目快結束時上級領導決定不做app,做移動端適配,emmm.....
大的問題不說了,網上都有,說下遇到的奇葩需求;由於使用Ionic框架,用一個做app的框架做了移動端適配,總是有點感覺在瀏覽器里面套了一個瀏覽器在裝我們的頁面,web原來是div高度撐出瀏覽器顯示高度瀏覽器出現滾動條,但是使用這個確認Ionic有自己的想法,看前端的層級目錄發現,在body下上來就是app-root根路徑,根路徑下就是ion-app,而這個ion-app就限定了高度和手機屏幕高度一致,如圖(1-1)所示,即無論ion-app里面頁面高如如何都不可能撐出瀏覽器高度,都會在里面出現滾動條,即對於部分瀏覽器支持當頁面高度撐出瀏覽器后下滑隱藏瀏覽器功能鍵使用該開發的移動web端無法實現,單是需求就是:在不改變使用框架的情況下需要實現下拉隱藏瀏覽器功能菜單功能;盡管心中一萬草泥馬在奔騰,但還是要做;

圖(1-1)
思路:既然是該ion-app限制了高度,是的內部的ion-content也與其高度保持了一致,那么我將ion-app的高度設置成當前頁面的高度,則就可以撐出瀏覽器高度,如果使用瀏覽器滾動功能,則需要禁用掉ion-content的在豎直方向上的滾動;
code:
目錄層級:

ts代碼:
declare const document: any; export class XXXXX implements OnInit, OnDestroy { isLeave = true; constructor(){} ngOnInit(){...} ionViewWillLeave() { this.isLeave = false; document.getElementById("ion-app-auto-height").style.height = '100%'; } ionViewDidEnter() { if (!this.isLeave) { let offsetHeight = document.getElementById("product-detail-t").offsetHeight + 'px'; document.getElementById("ion-app-auto-height").style.height = offsetHeight; this.isLeave = true; } } ngAfterViewChecked() { if (document.getElementById("product-detail-t").offsetHeight != 0) { let offsetHeight = document.getElementById("product-detail-t").offsetHeight + 'px'; if (document.getElementById("ion-app-auto-height").style.height !== offsetHeight) { if (this.isLeave) { document.getElementById("ion-app-auto-height").style.height = offsetHeight; } } } }
注意:上述代碼標紅的位置需要替換成html中ion-app定義的id以及當前頁面最外層div定義的id;
特別注意:body需要設置一下屬性,否則會導致撐出頁面隱藏;
body{
position: unset;
overflow: auto
}
頁面渲染完成,將當前頁面div的高度賦值值ion-app的高度,禁用ionic的滾動功能,並且頁面撐出瀏覽器,便可順利實現需求(在iso和android測試均通過);
問題2:由於改變了展示方式,導致了之前的瀏覽器滾動到底在在數據無法使用,即ion-infinite-scroll控件失效,這里自己寫了一個控件來實現:
2.1目錄結構: 
html內容:功能占位
<p></p>
scss內容:空
ts文件內容:
import {Component, HostListener, Input, OnDestroy, OnInit} from '@angular/core';
import {TablePageService} from '../table-page/table-page.service';
import {TablePageParams} from '../table-page/table-page.service';
import {debounceTime, take} from 'rxjs/operators';
declare const document: any;
@Component({
selector: 'app-infinite-scroll',
templateUrl: './infinite-scroll.component.html',
styleUrls: ['./infinite-scroll.component.scss']
})
export class InfiniteScrollComponent implements OnInit{
@Input() service: TablePageService<any>;
@HostListener('window:scroll', ['$event']) public onScroll = ($event) => {
//客戶端高度
var clientH = document.documentElement.clientHeight*1;
//body高度
var bodyH = document.getElementById("ion-app-auto-height").style.height.replace('px','')*1;
//滾動的高度
var scrollTop = (document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset)*1;
//滾動到底部60以內
if ((bodyH - clientH - scrollTop)*1 < 100) {
if (!this.flag) {
if (!this.isLast) {
this.query();
}
}
this.flag = true;
} else {
this.flag = false;
}
}
flag = false;
isLast = false;
type = '01';
private data: any[] = [];
private tablePageParams: TablePageParams;
constructor() { }
ngOnInit() {
this.service.params.pipe(debounceTime(200)).subscribe(params => {
if (this.type != params.type) {
this.type = params.type;
this.flag = false;
this.isLast = false;
}
this.tablePageParams = new TablePageParams(params, 1);
this.data = [];
this.query();
});
}
query() {
this.service.queryPage(this.tablePageParams)
.pipe(take(1))
.subscribe(result => {
this.tablePageParams.pageNumber++;
this.data = this.data.concat(result.result);
this.service.result.next(this.data);
if (result.currentPageNo === result.totalPageCount || this.data.length > 500) {
this.isLast = true;
}
});
}
}
前端定義的TablePageService接口:
import {Subject, ReplaySubject, Observable} from 'rxjs';
export abstract class TablePageService<T> {
result = new Subject<T[]>();
params = new ReplaySubject<any>();
constructor() {
}
query(params = {}) {
this.params.next(params);
}
complete() {
this.result.complete();
this.params.complete();
}
abstract queryPage(params: TablePageParams): Observable<TablePageResult<T>>;
}
export class TablePageParams {
pageNumber: number;
pageSize: number;
params: any;
totalPage: number;
constructor(_params: any = {}, _pageNumber = 1, _pageSize = 20, _totalPage = 1) {
this.params = _params;
if (typeof _pageNumber !== 'number') {
_pageNumber = parseInt(_pageNumber, 20);
}
this.pageNumber = _pageNumber > 0 ? _pageNumber : 1;
this.pageSize = _pageSize;
this.totalPage = _totalPage;
}
}
export class TablePageResult<T> {
currentPageNo = 1;
pageSize = 20;
result: T[];
totalCount = 0;
totalPageCount = 1;
constructor() {
}
}
exports出該控件;
2.2 控件使用:
在html中引入控件,並傳入service;

在ts文件中,定義該service,
ts文件:
import {Component, OnDestroy, OnInit} from '@angular/core';
import {Subscription} from 'rxjs/index';
import {OrderProductInfo} from '../../../core/aftersales-core/domain/orderform';
import {AftersalesTablePageService} from '../aftersales-table-page.service';
import {AfterSalesIndexService} from '../index/after-sales-index-service';
declare const document: any;
@Component({
selector: 'app-aftersales-apply',
templateUrl: './aftersales-apply.component.html',
styleUrls: ['./aftersales-apply.component.scss'],
providers: [AftersalesTablePageService]
})
export class AftersalesApplyComponent implements OnInit, OnDestroy {
orderProductList: OrderProductInfo[] = [];
private subscriptions: Subscription[] = [];
isLeave = true;
constructor(public tableService: AftersalesTablePageService) {
}
ngOnInit() {
const pageSub = this.tableService.result.asObservable().subscribe(result => { //監聽result數據的變化
this.orderProductList = result as [];
});
this.subscriptions.push(pageSub);
this.query();
}
query() {
this.tableService.query();
}
ngOnDestroy(): void {
this.subscriptions.forEach(_item => _item.unsubscribe());
}
ionViewWillLeave() {
this.isLeave = false;
document.getElementById("ion-app-auto-height").style.height = '100%';
}
ionViewDidEnter() {
if (!this.isLeave) {
let offsetHeight = document.getElementById("aftersales-apply-t").offsetHeight + 'px';
document.getElementById("ion-app-auto-height").style.height = offsetHeight;
this.isLeave = true;
}
}
ngAfterViewChecked() {
if (document.getElementById("aftersales-apply-t").offsetHeight != 0) {
let offsetHeight = document.getElementById("aftersales-apply-t").offsetHeight + 'px';
if (document.getElementById("ion-app-auto-height").style.height !== offsetHeight) {
if (this.isLeave) {
document.getElementById("ion-app-auto-height").style.height = offsetHeight;
}
}
}
}
}
實現service代碼示例,具體查詢某一接口:
@Injectable({
providedIn: null
})
export class AftersalesTablePageService extends TablePageService<any> {
constructor(private table: TableService) {
super();
}
queryPage(tablePageParams: TablePageParams) {
return this.table.queryPage<OrderProductInfo>('/orderform/getorderproductpage.do', tablePageParams);
}
}
tableService,具體http請求以及返回數據的封裝;

最終效果:

實現距離底部100px,加載新數據;
