600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > android 加载静态网页 React Native:如何在WebView内加载SPA或本地静态HTML页面?

android 加载静态网页 React Native:如何在WebView内加载SPA或本地静态HTML页面?

时间:2019-01-29 17:45:40

相关推荐

android 加载静态网页 React Native:如何在WebView内加载SPA或本地静态HTML页面?

React Native:如何在WebView内加载SPA或本地静态HTML页面?

React Native WebView允许你使用uri属性加载可公开访问的资源,就像程序内的一个浏览器。但是,当你要加载本地html或者SPA应用时,它并不是那么简单。

通常在APP内部接入WebView时,我们可以有两种选择,一是通过uri指向一个公开的网页地址,从而加载远程网页。二是指向一个本地的静态HTML文件路径,从而加载本地网页。两种方式各有优劣,方法一接入简单但不可离线且加载时间不可控,方法二接入复杂但可离线访问资源都在本地加载速度快。

选泽这两种接入方式需要视情况而定,当需要接入网络的资源大而多,如一些SPA应用,可以考虑使用本地接入, 若只是接入一些简单且常变的活动页时,可以考虑远程接入。 本篇文章是针对第二种本地接入方式进行分享。

目标要求

所有的静态资源如 css,js,img等都应该存储在本地。

同时支持android和ios

所有平台都从一个目录中读取文件,避免冗余。

设计方案

第一步、静态资源目录

在React Native项目根目录中添加Static.bundle文件夹。

将你的SPA应用或者本地HTML文件移动到此文件夹中。

静态资源文件夹以.bundle结尾的原因在于,iOS对于以.bundle结尾的文件夹在打包后能够保持内部的资源引用路径。

第二步、iOS静态资源设置

打开xcode项目并选中以项目名称命名的第一个文件夹,并右键添加文件

找到第一步设置的Static.bundle文件夹并添加,注意不要勾选Copy items if needed。

Copy items if needed如果勾选则会将资源拷贝一份到iOS目录下,与初始目标:所有平台都从一个目录中读取文件相悖

第三步、Android资源路径设置

打开android/app/build.gradle文件,修改如下

android {

...

sourceSets {

main {

asset.srcDirs = ['src/main/assets', '../../Static.bundle']

}

}

}

WebView访问本地HTML

设置HTML路径

let source = (Platform.OS === 'android' ? 'file:///android_asset/' : '') + `Static.bundle/index.html`;

ref={ref => (this.webViewRef = ref)}

onMessage={this.onMessage}

originWhitelist={['*']}

allowFileAccess={true}

source={{uri: source}}

javaScriptEnabled={true}

decelerationRate='normal'

scrollEnabled={true}

useWebKit={true}

mediaPlaybackRequiresUserAction={true}

mixedContentMode="compatibility"

allowingReadAccessToURL="*"

// onLoadEnd={() => this.setState({ loading: false })}

/>

至此,接入本地HTML已大致完毕, 可在iOS和Android平台测试。

传递参数

在React Native中打开本地HTML应用该如何传递参数呢?

现有解决方案是通过WebView提供injectedJavaScript参数传递。

let injectJs = `(function(){location.href="#url?access_token=${access_token}&user_id=${user_id}"}())`

injectedJavaScript={injectJs}

/>

Loading

若是本地HTML中的内容需要ajax请求获取,则一般会配置Loading动画,而我们加载WebView本身亦是需要Loading动画, 若是不做处理,则会出现两个Loading交替现象,用户体验下降。

解决方案是通过WebView的事件传递,在WebView中通过ajax将数据加载完毕后,通过window上的事件通知 React Native端解除Loading.

// html

window.ReactNativeWebView.postMessage(JSON.stringify({

type: "loadEnd"

}));

// react native

onMessage = event => {

try {

const action = JSON.parse(event.nativeEvent.data);

switch(action.type) {

case "loadEnd":

this.setState({loading: false});

break;

} catch (error) {

console.log(error);

}

}

单页应用异步路由处理

若是本地SPA应用中包含一些异步路由渲染的页面则不能直接接入使用, 原因在于在浏览器中,异步路由的实现是通过ajax请求异步获取页面内容, 但是在本地的单页应用中,由于跨域问题,是不支持以ajax获取内容的。

解决: 将所有异步文件在index.html中导入。

调试

由于WebView是使用本地绝对路径作为uri,最终访问的是App内容文件,所有React Native的热更新不会起作用,若HTML文件发生改变,则需要重新build。

总结

通过方案设计和接入设计,最终完成了我们的三点目标要求

通过.bundle文件夹保持了xcode打包后的资源结构,可以放心将所有资源存储到本地

通过对Android资源路径的设置,解决了冗余问题

通过对平台的判断,添加前缀兼容了所有平台

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。