用angular7+Ionic做移动App做成了webapp引发的系列问题

Posted code-sayhi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用angular7+Ionic做移动App做成了webapp引发的系列问题相关的知识,希望对你有一定的参考价值。

背景:公司前端开发一直使用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,加载新数据;

以上是关于用angular7+Ionic做移动App做成了webapp引发的系列问题的主要内容,如果未能解决你的问题,请参考以下文章

初探IONIC不会Native可不可以开发APP?

一个简单移动页面ionic打包成app

Ionic 创建项目

Ubuntu虚拟机中使用Ionic开发移动app应用

超好用的移动框架--Ionic--构建APP侧边栏 底部选项卡 轮播图 加载动画

Ionic+AngularJS 开发之『个人日常管理』App