用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,加载新数据;

原文地址:https://www.cnblogs.com/code-sayhi/p/11126883.html

时间: 2024-10-19 20:34:47

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

Ionic开发Hybrid App问题总结

http://ionichina.com/topic/5641b891b903cba630e25f10 http://www.cnblogs.com/parry/p/issues_about_build_hybrid_app_with_ionic.html 作者:Parry 出处:http://www.cnblogs.com/parry/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 此篇文章主要整理了最近在

Ionic之顺带APP

1:Ionic简介 官方:我们设计ionic来帮助 web 开发人员能够像开发网站一样开发出强大的移动APP应用. ionic是一个html5开发APP的框架,在开发运行效率可以说是最好的H5框架,把传统的JS开发变成面向对象开发,可控性比较好(个人实在是驾驭不了代码量较大的JS). 2:Ionic版“顺带”APP项目 项目地址:https://github.com/DaLeiGe/Ionic-shundai 结合这十来天对ionic的学习,使用ionic重新开发了一个我参加计算机作品赛时的项目

做一个App究竟要花多少钱?

作为互联网从业者,被外行的朋友们问及最多的问题是: “做一个网站需要多少钱?”或者“做一个APP需要多少钱?”. 作为做过完整网站项目和APP的人,今天从产品经理的角度,一起来算一下中小型APP从无到有需要做哪些工作,以及为达成使命,需要付出多少金钱代价. 以下内容的前提是: 深圳.移动互联网方向.包含研发一个新产品过程中一些常见的工作,并非十全十美. 首先假设在做APP之前我们已经有了一个成熟的团队(这是非常幸运的前提,很多产品研发进度极其缓慢的原因之一就是在过程中不断在招人),团队的结构以架

多快好省的做个app开发

从技术经理的角度算一算,如何可以多快好省的做个app [导读]前端时间,一篇“从产品经理的角度算一算,做个app需要多少钱”的文章在网上疯传,可见大家对互联网创业的热情!这次,从一名技术经理的角度再给大家分析一下,如何使用跨平台开发技术为你节省上百万的开发成本.所谓“跨平台”开发技术,就是使用一种语言和一种开发工具同时支持几种不同的手机/平板设备,这样做不仅仅省钱而且开发效率高,可以让你更快的推出新版本和新功能! 作为一名软件工程顾问,我曾参与过很多的项目,主要为软件团队进行开发工具和方法论方面

从技术经理的角度算一算,如何可以多快好省的做个app

[导读]前端时间,一篇“从产品经理的角度算一算,做个app需要多少钱”的文章在网上疯传,可见大家对互联网创业的热情!这次,从一名技术经理的角度再给大家分析一下,如何使用跨平台开发技术为你节省上百万的开发成本.所谓“跨平台”开发技术,就是使用一种语言和一种开发工具同时支持几种不同的手机/平板设备,这样做不仅仅省钱而且开发效率高,可以让你更快的推出新版本和新功能! 作为一名软件工程顾问,我曾参与过很多的项目,主要为软件团队进行开发工具和方法论方面的咨询/培训/指导,我接触过不下100个各种类型/大小

爱加密有效抵御“恐吓式”诈骗短信侵袭,做移动App应用安全保护者!

近日,电信诈骗家族中又出现新成员--"恐吓式"诈骗短信.一位网友发帖称,收到陌生号码发来的"恐吓短信",对方自称是"恶贯满盈的人渣",该条敲诈短信的内容如下:"警告,很不幸你遇到我们这些恶贯满盈的人渣,限24小时内打3000元到(622202×××××),否则7日之内你家宝贝出现任何不幸,不要怪自己太愚蠢吝啬,我们承诺只要你配合,仅骚扰你这一次."网友在公布对方银行卡号和手机号码的同时,希望引起大家的注意. 爱加密有效抵御&q

做一个 App 前需要考虑的几件事

做一个 App 前需要考虑的几件事 来源:limboy的博客 随着工具链的完善,语言的升级以及各种优质教程的涌现,做一个 App 的成本也越来越低了.尽管如此,有些事情最好前期就做起来,避免当 App 有了一定规模后,再感慨当初为什么没有多留点心. 完善的日志系统 以 iOS 为例,有时图方便,就直接用 NSLog 了,甚至线上都一直开着.一方面会影响性能,尤其是输出比较频繁的时候,另一方面也容易泄露敏感信息,所以一般做法是在 Release 模式下禁用 NSLog,比如在 pch 文件中,通过

做个APP

长话短说就是我想做个App,吵的很火的PhoneGap想要用一下,于是拿HTML5和JS prototyping 这个两个语言(姑且称二者为语言)的用户体验一直都不是特别好 而且为了个responsive html5 canvas也十大费周章,与类似 foundation的framework不兼容因为window resize已经被用了.再者你的所有的asset都必须是适量而且和screen size的相对比例大小需要搞清楚.总算搞的okay了放到iphone上交互的时候canvas会重新渲染闪

做一个App前需要考虑的几件事

本文转载于文章原文链接,版本归原作者所有! 随着工具链的完善,语言的升级以及各种优质教程的涌现,做一个 App 的成本也越来越低了.尽管如此,有些事情最好前期就做起来,避免当 App 有了一定规模后,再感慨当初为什么没有多留点心. 此处由标哥的技术博客站长点评: 看完本篇文章之后,也让我想起了不少以前做过的蠢事,做过很多重复的工作.之前在项目中使用过cocoalumberjack,个人感觉是很不错的日志管理框架.当然,不一定要求使用它,也在另一家公司里,原来的人将NSLog重定义了,改写了输出,