来源:http://blog.csdn.net/qq_15096707/article/details/55194781
前言
我们会遇到这样的一个需求:像是在 Ionic2 中加载一个网页,如:在Ionic2中加载一个H5页面,页面的内容可以为资讯的详情或者活动详情等等。那么在Ionic2中就需要有这样一个东西,用来加载H5页面。在Android原生中有WebView。那在Ionic2中有什么呢?
ionic-native
在Ionic2中,ionic-native包中提供了,如 InAppBrowser 和 ThemeableBrowser 等这两个cordova插件用来打开一个“WebView”类似的窗口,用来加载页面。
ThemeableBrowser的使用
如使用ThemeableBrowser插件,打开一个新的窗口加载页面,效果如下:
使用ThemeableBrowser可以参考,我写过的一篇文章《 ionic2中ThemeableBrowser插件的使用——App内嵌浏览器》。
ThemeableBrowser的缺点
1. 使用ThemeableBrowser时,在定义顶部标题栏样式的时候显得繁琐,不容易定义与当前APP主题一致de样式;
2. 浏览器调试时无法调用cordova插件,需要真机运行。
3. 在标题栏添加一些自定义的菜单项也显得不那么容易。
使用iframe仿浏览器加载页面
为了让这个iframe变得更加通用,同时更像一个“浏览器”。在这里,在Ionic2中定义一个BrowserPage页面,我们在打开该页面的时候需要传递browser的配置参数,配置如:页面标题、访问的页面链接、定义分享配置等。
在这个浏览器中定义了一个popover菜单,默认只拥有 “刷新”(刷新页面)、“关闭”(关闭当前页面)的功能。
browser.html
这里定义了“浏览器”的页面,其中包含了加载页面时显示的进度条(可以说是伪进度条,没有计算真正访问页面时候的进度。)
<ion-header no-shadow>
<ion-navbar class="page-navbar">
<ion-title>{{browser.title}}</ion-title>
<ion-buttons end>
<button ion-button icon-only (click)="presentPopover($event)">
<ion-icon name="more"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content class="content"> <!--scroll="true" overflow-scroll="true"-->
<div class="progress" [hidden]="browser.isLoaded">
<div class="progress-inner" id="progress"></div>
</div>
<iframe id="iframe" class="iframe"
sandbox="allow-scripts allow-top-navigation allow-pointer-lock allow-same-origin allow-popups allow-forms"
[src]="browser.secUrl"
(load)="loaded()">
</iframe>
</ion-content>
<panel-share [(isShow)]="shareConfig.isShow" [share]="browser.share"></panel-share>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
注:这里定义了一个 panel-share 组件,用于显示分享功能(如:微信分享、朋友圈分享、QQ分享等)。用户可以自己定义 点击菜单栏上“分享”后显示的分享组件。这里只是举个栗子。
browser.scss
定义browser的样式,进度条样式。
page-browser {
$progress-height: 0.2rem;
//$progress-bg: #d43f3a;
//$progress-bg: linear-gradient(-45deg, #333 100%, #324512 60%,rgba(255,255,255,0.5) 0%);
//$progress-bg: linear-gradient(left, #5bd8ff, #ff0000);
//$progress-bg: linear-gradient(-45deg, rgba(255,255,255,0.5)0%, #324512 60%,#333 100%);
$progress-bg: #77b6ff;
/*.scroll-content {
overflow: hidden;
}*/
.content {
height: 100%;
}
.progress{
position: absolute;
top: 0;
right: 0;
left: 0;
height: $progress-height;
background: #f5f5f5;
z-index: 200;
.progress-inner{
width: 0;
background: $progress-bg;
position: absolute;
top: 0;
left: 0;
bottom: 0;
box-shadow: 0 0 10px rgba(119,182,255,0.7);
-webkit-transition: width 0.4s ease;
transition: width 0.4s ease;
}
}
.iframe {
width: 100%;
height: 100%;
position: absolute;
overflow: auto;
border: none;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 4
browser.ts定义浏览器功能
主要是加载页面时显示进度条、刷新页面、分享回调(如果打开browser页面时,传入的分享的配置参数)等功能。
/**
* Created by DreamBoy on 2016/11/21.
*/
import { Component } from '@angular/core';
import { NavController, NavParams, PopoverController } from 'ionic-angular';
import { DomSanitizer } from "@angular/platform-browser";
import { BrowserPopoverPage } from "./browser-popover";
@Component({
selector: 'page-browser',
templateUrl: 'browser.html'
})
export class BrowserPage {
browser: any = {
isLoaded: false, // 网页是否被加载
proObj: null, // 进度条对象
progress: 0, // 网页访问的进度条
secUrl: '', // 安全链接
title: '加载中',
url: '',
share: null // 是否具有分享功能(传递一个分享对象ShareModel过来)
};
shareConfig: any = {
isShow: false
}; // 分享控制的配置
constructor(public navCtrl: NavController,
private params: NavParams,
private sanitizer: DomSanitizer,
private popoverCtrl: PopoverController) {
let browser = this.params.get('browser');
if(browser) {
this.browser.title = browser.title;
this.browser.url = browser.url;
this.browser.secUrl = this.sanitizer.bypassSecurityTrustResourceUrl(browser.url);
if(browser.share) {
this.browser.share = browser.share;
}
} else {
this.browser.secUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.browser.url);
}
this.reload();
}
ionViewDidLoad() {
if(!this.browser.proObj) {
this.browser.proObj = document.getElementById('progress');
}
this.onprogress();
}
// 生成随机数
private random(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1) + min);
}
// 网页访问进度
private onprogress() {
// 随机时间
let timeout = this.random(10, 30);
let timer = setTimeout(() => {
if(this.browser.isLoaded) {
this.browser.proObj.style.width = '100%';
clearTimeout(timer);
return;
}
// 随机进度
this.browser.progress += this.random(1, 5);
// 随机进度不能超过 90%,以免页面还没加载完毕,进度已经 100% 了
if(this.browser.progress > 90){
this.browser.progress = 90;
}
this.browser.proObj.style.width = this.browser.progress + '%';
this.onprogress();
}, timeout);
}
// 如果iframe页面加载成功后
loaded() {
this.browser.isLoaded = true;
}
// 显示Popver选项
presentPopover(myEvent) {
let cb = {
refresh: () => {
this.reload();
},
close: () => {
this.navCtrl.pop();
},
share: null
};
if(this.browser.share) {
cb.share = () => {
this.share();
}
}
let popover = this.popoverCtrl.create(BrowserPopoverPage, {
callback: cb
});
popover.present({
ev: myEvent
});
}
// 重新加载页面
reload() {
let title = this.browser.title;
let url = this.browser.secUrl;
this.browser.title = '加载中';
this.browser.secUrl = this.sanitizer.bypassSecurityTrustResourceUrl('');
setTimeout(() => {
this.browser.isLoaded = false;
this.browser.progress = 0;
if(!this.browser.proObj) {
this.browser.proObj = document.getElementById('progress');
}
this.onprogress();
this.browser.title = title;
this.browser.secUrl = url;
}, 10);
}
// 分享页面(作为popover的回调)
share() {
this.shareConfig.isShow = true;
/*if(this.browser.share) {
SocialSharing.share(this.browser.share.title, this.browser.share.content, '', this.browser.share.url).then(() => {
}, (err) => {
// Error!
alert('错误:分享失败!' + err);
});
}*/
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
browser-popover.ts菜单项
点击对应的功能,调用 browser.ts 中的方法。
/**
* Created by admin on 2016/11/22.
*/
import { Component } from '@angular/core';
import { ViewController, NavParams } from "ionic-angular";
@Component({
template: `
<ion-list>
<button ion-item detail-none (click)="refresh()">刷新</button>
<button ion-item detail-none (click)="share()" *ngIf="parentCallback.share">分享</button>
<button ion-item detail-none (click)="close()">关闭</button>
</ion-list>
`
})
export class BrowserPopoverPage {
parentCallback: {refresh: () => void, share?: () => void, close: () => void};
constructor(public viewCtrl: ViewController,
private navParams: NavParams) {
this.parentCallback = this.navParams.data.callback;
}
// 刷新
refresh() {
this.parentCallback.refresh();
this.viewCtrl.dismiss();
}
// 分享
share() {
this.parentCallback.share();
this.viewCtrl.dismiss();
}
close() {
this.viewCtrl.dismiss();
this.parentCallback.close();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
定义 ShareModel 模型
这里的share模型主要用于调用分享时作为传入browser的参数的类型。
/**
* Created by admin on 2017/1/18.
*/
export class ShareModel { // 分享
title: string; // 标题
banner: string; // 标语提示
descr: string; // 描述
thumb: string; // 显示的缩略图
url: string; // 链接
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
BrowserPage的使用示例
基本使用:
this.navCtrl.push(this.browserPage, {
browser: {
title: '页面名称',
url: '这里放置访问的页面链接'
}
});
- 1
- 2
- 3
- 4
- 5
添加“分享”功能:
let share: ShareModel = new ShareModel();
share.title = '标题';
share.banner = '标语提示';
share.thumb = '缩略图';
share.descr = '描述';
share.url = '分享的链接';
this.navCtrl.push(this.browserPage, {
browser: {
title: '页面名称',
url: '这里放置访问的页面链接',
share: share
}
});
- 1
- 2
- 3
BrowserPage使用效果
打开一个页面:
打开菜单:
调用分享,分享页面链接:
注意事项
在iOS中iframe加载不了网页的问题(iframe白屏)
需要在config.xml添加“allow-navigation”,允许设置多个域下的访问,如(下面这个是初始项目给出的栗子):
<allow-navigation href="http://ionic.local/*"/>
- 1
通用的写法有(当前安全性就低一些咯,可以设置允许访问的几个域):
<allow-navigation href="*" />
在iOS中iframe加载页面后页面不可滚动的问题
在iframe的容器,如div,增加一个 -webkit-overflow-scrolling: touch;
属性。如:
.scroll-wrapper {
-webkit-overflow-scrolling: touch;
overflow-y: scroll;
/* 提示: 请在此处加上需要设置的大小(dimensions)或位置(positioning)信息! */
}
.scroll-wrapper iframe {
/* 你自己指定的样式 */
}
- 1
- 2
- 3
- 4
- 5
在Ionic2中的.scroll-content类样式包含了 -webkit-overflow-scrolling: touch;
属性,所以不会出现这样的问题(页面不可滚动的问题)。那如果我们定义 .scroll-content 的overflow属性为 hidden。那就会出现这样的问题了。