React Native 加载H5页面的实现方法

目录
  • 一、基本使用
    • 1.1 RN向H5发送数据
    • 1.2 H5向RN传递数据
    • 1.3 双向传值
  • 二、属性和方法
    • 2.1 属性
    • 2.2 方法
  • 三、使用示例
    • 3.1 加载外源网页信息
    • 3.2 登陆场景
    • 3.3 功能模块嵌入到 RN 中
    • 3.4 完整示例

一、基本使用

作为目前流行的移动跨平台开发技术,React Native 提供了一个使用 JavaScript 构建原生跨平台移动应用的强大框架。使用React Native开发时,经常会遇到加载H5网页的需求,此时需要用到react-native-webview插件来执行H5网页的加载。

使用插件之前,需要先安装npm i react-native-webview插件,命令如下:

npm i react-native-webview

然后,就可以在业务代码中引入react-native-webview 插件的WebView组件,比如:

<WebView  ref={ (webView) => this.webView = webView }
          originWhitelist={ ['*'] }
          // 布尔值,指定WebView中是否启用JavaScript。只在Android上使用,因为在iOS上默认启用了JavaScript。
          javaScriptEnabled={ true }
          // 布尔值,指定是否开启DOM本地存储
          domStorageEnabled={ true }
          // 允许文件上传
          allowFileAccess={ true }
          // 在webView内部网页中,调用window.postMessage可以触发此属性对应的函数,通过event.nativeEvent.data获取接收到的数据,实现网页和RN之间的数据传递
          onMessage={ this._onMessage }
          //初始化调用方法
          onLoad={() => { this.handleInjectJavascript();}}
          // 加载时强制使用loading转圈视图,如果为true,webview可能会加载失败,显示为空白
          startInLoadingState={false}
          // webview加载错误页面
          renderError={this.renderErrorView}
          // 网络路径
          // 也可以为本地路径 source={ {uri: 'http://192.168.1.1111:8080/'} }
          source={ {uri: 'http://www.baidu.com/'} } />

使用WebView组件加载H5页面时,必然会涉及到交互。

1.1 RN向H5发送数据

如果是RN向H5发送数据,那么可以调用onLoad函数的handleInjectJavascript() 方法。

 //RN webview 向 vue发送数据
 handleInjectJavascript = (data) => {
     // 拼接数据为方法
     const injectJavascriptStr =  `(function() {
     	window.WebViewBridge.onMessage(${JSON.stringify(data)});
     })()`;
     // 通过 injectJavaScript  将数据传递给WebView页面,并立即执行为js
     if(this.webView) {
     	this.webView.injectJavaScript(injectJavascriptStr)
     }
 }

如果有回调的结果,需要在mounted生命周期函数中,

 mounted() {
    window.WebViewBridge = {
      onMessage: this._onMessage //在window上挂载一个onMessage方法,RN会调用
    }
    // 自定义事件后直接触发:
    const event = new Event('WebViewBridge')
    window.dispatchEvent(event);
 },
 methods: {
    // 接收 RN 发送的消息
    _onMessage(data) {
      let that = this;
      console.log('data ------- ',JSON.stringify(data)); // 'hello world'
    }
  }

以上就是RN向H5 传值的过程,其具体过程:RN中给 window.WebViewBridge 增加一个名为 onMessage 的方法,H5初始化页面会对应给出onMessage 指向的方法,在此代码块 指向 _onMessage 方法并执行。

1.2 H5向RN传递数据

如果是H5页面主动向RN发送数据,需要用到postMessage方法。

  mounted() {
    // 自定义事件后直接触发:
    const event = new Event('WebViewBridge');
    window.dispatchEvent(event);
  },
  methods: {
    // 向rn发送消息, 将值 'hello world' 挂载到 postMessage
    _postMessage('hello world') {
        window.ReactNativeWebView.postMessage(data);
    }
  }

RN 页面在接收到 vue 传输的数据之后执行 onMessage 函数方法。

onMessage={ this._onMessage }
 _onMessage = (event) => {
        console.log('接收vue发来的消息onMessage', event.nativeEvent.data);
  }

1.3 双向传值

当然,有时候,也会涉及到多次双向传递的情况。

  mounted() {
    window.WebViewBridge = {
      onMessage: this._onMessage,
      receiveMessage: this._receiveMessage //在window上挂载一个receiveMessage方法,RN自行调用
    }
    const event = new Event('WebViewBridge')
    window.dispatchEvent(event);
  },
  methods: {
    // 向rn发送消息
    _postMessage('wow,RN!!') {
        window.ReactNativeWebView.postMessage(data);   // 将值 'wow,RN!!' 挂载到 postMessage
    },
    // 二次或多次接收RN发送消息
     _receiveMessage(data){
      let that = this;
      console.log('data receiveMessage-------  ',JSON.stringify(data));
     }
  }

RN 页面在接收到 H5 传输的数据之后执行 onMessage 函数。

onMessage={ this._onMessage }
 // 接受H5发送来的消息
 _onMessage = (event) => {
        console.log('接收H5发来的消息onMessage', event.nativeEvent.data); 

        const injectJavascriptStr =  `(function() {
 	   window.WebViewBridge.receiveMessage(${JSON.stringify('hello,vue2!!! ')});
        })()`;
        this.webView.injectJavaScript(injectJavascriptStr);
  }

二、属性和方法

使用 WebView 组件我们可以通过 url 来加载显示一个网页,也可以传入一段 html 代码来显示。该组件的引入是解决 React Native 内嵌 H5 的比较好的解决方案,该组件自带的常用属性和方法我们可以归纳如下:

2.1 属性

  • source:在 WebView 中载入一段静态的 html 代码或是一个 url(还可以附带一些 header 选项)
  • automaticallyAdjustContentInsets:设置是否自动调整内容。格式:boolean
  • contentInset:设置内容所占的尺寸大小。格式为{top:number,left:number,bottom:number,right:number}
  • injectJavaScript:当网页加载之前注入一段 js 代码。其值是字符串形式。
  • startInLoadingState:是否开启页面加载的状态,其值为 true 或者 false。
  • bounces(仅iOS):回弹特性。默认为 true。如果设置为 false,则内容拉到底部或者头部都不回弹。
  • scalesPageToFit(仅iOS):用于设置网页是否缩放自适应到整个屏幕视图,以及用户是否可以改变缩放页面。
  • scrollEnabled(仅iOS):用于设置是否开启页面滚动。
  • domStorageEnabled(仅Android):用于控制是否开启 DOM Storage(存储)。
  • javaScriptEnabled(仅Android):是否开启 JavaScript,在 iOS 中的 WebView 是默认开启的。

2.2 方法

  • onNavigationStateChange:当导航状态发生变化的时候调用。
  • onLoadStart:当网页开始加载的时候调用。
  • onError:当网页加载失败的时候调用。
  • onLoad:当网页加载结束的时候调用。
  • onLoadEnd:当网页加载结束调用,不管是成功还是失败。
  • renderLoading:WebView组件正在渲染页面时触发的函数,只有 startInLoadingState 为 true 时该函数才起作用。
  • renderError:监听渲染页面出错的函数。
  • onShouldStartLoadWithRequest(仅iOS):该方法允许拦截 WebView 加载的 URL 地址,进行自定义处理。该方法通过返回 true 或者 false 来决定是否继续加载该拦截到请求。

三、使用示例

3.1 加载外源网页信息

import React,{Component} from 'react'
import {
    StyleSheet,
    View,
    Text,
    WebView,
} from 'react-native'
export default class Root extends Component{
    constructor(props){
        super(props)
    }
    render(){
        return (
            <View style={styles.container}>
                <WebView
                  source={{uri: 'https://www.baidu.com'}}
                    domStorageEnabled={true}
                    javaScriptEnabled={true}
                    startInLoadingState={true}
                    automaticallyAdjustContentInsets={true}>
                </WebView>
            </View>
        )
    }
}
const styles = StyleSheet.create({
    container:{
        flex:1,
    },
})

上面是一个加载百度首页的示例。

3.2 登陆场景

一款 toB 的 app,面对很多家客户,每家客户都有自己的登录系统界面,并且客户要求接入自己的登录系统。这个时候就需要 webview 接入登录界面之后,进行一些 “值拦截”,进行登录状态判断。这里主要用到 webview 的 onNavigationStateChange 参数。此方法会在当导航状态发生变化的时候调用,例如取到下面的参数:

   {
      "canGoBack": false,
      "canGoForward": false,
      "loading": true,
      "navigationType": "other",
      "target": 229,
      "title": "",
      "url": "https://www.baidu.com/"
   }

这里主要注意 url 字段,网页内部登录完成之后,可以发起一个重定向,前端关注 url 变化,进行登录状态的判断,同时重定向的 url 中可以拼接一些登录信息字段,用于前端登录状态校验等。

{ "url": "https://www.baidu.com ? sessionId=xxx & username= xxx" }

3.3 功能模块嵌入到 RN 中

将 webview 作为功能模块载体,这个时候就会涉及到用户交互,需要 rn 与 h5 进行值的互相传递。此时就要react native 向 web 中注入 js,web 也可以主动回传数据到 react native中。webview 组件提供了 injectedJavaScript 用于向 h5 注入js,在 h5 中使用 window.ReactNativeWebView.postMessage 进行主动的回调,并且在 webview 的 onMessage 中进行字段的监听,以此就可以完成 react 和 h5 之间的数据交互。

const injectJSStr = `
  window.injectStr='我是注入的字段';
  var div = document.getElementById('testID');
  div.style.color='red';
  div.style.fontSize='100px';
`;
const html = `
    <html>
    <head></head>
    <body>
      <script>
        setTimeout(function () {
          window.ReactNativeWebView.postMessage(window.injectStr)
        }, 2000)
      </script>
      <div id='testID'>Hello Word</div>
    </body>
    </html>
 `;
  ......
<View style={{flex: 1}}>
    <WebView
        source={{html}}
        injectedJavaScript={injectJSStr}
        onMessage={event => {
        alert(event.nativeEvent.data);
        }}
    />
</View>

3.4 完整示例

例如,有下面一个需求:RN里面通过触发刷新使H5界面的背景色可以随机改变;H5 界面我们写一个简单的 input 输入使输入的文字可以在RN 显示出来。

import React, {Component} from 'react';
import {Text, StyleSheet, View, Button} from 'react-native';
import WebView from 'react-native-webview';
export default class App extends Component {
  state = {colorIndex: 0, tip: '原生的Text组件,等webview中的发送。。'};
  changeColor = () => {
    this.webview.reload();
    let colorIndex = this.state.colorIndex;
    colorIndex = ++colorIndex % 5;
    this.setState({colorIndex});
  };
  recieve = msg => {
    let data = msg.nativeEvent.data;
    let uname = JSON.parse(data).uname;
    this.setState({tip: uname});
  };
  render() {
    let colors = ['gray', 'yellow', 'red', 'antiquewhite', 'white'];
    let scriptStr = `document.body.style.backgroundColor='${
      colors[this.state.colorIndex]
    }'`;
    return (
      <View style={{flex: 1}}>
        <Button title="刷新WebView的背景色" onPress={this.changeColor} />
        <Text style={{fontSize: 30}}>{this.state.tip}</Text>
        <WebView
          onMessage={this.recieve}
          ref={ref => (this.webview = ref)}
          injectedJavaScript={scriptStr}
          source={{uri: 'http://192.168.180.241:8080/test.html'}}
        />
      </View>
    );
  }
}

H5的代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <input class="info" name="uname" value="John" />
    <br>
    <button class="info">发送给原生组件</button>
    <script>
        document.querySelector('button').addEventListener('click', () => {
            let uname = document.querySelector('input[name="uname"]').value
            let msg = JSON.stringify({
                uname
            })
            window.ReactNativeWebView.postMessage(msg)
        })
    </script>
</body>
</html>

到此这篇关于React Native 加载H5页面的文章就介绍到这了,更多相关React Native H5页面内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解react native页面间传递数据的几种方式

    1. 利用react-native 事件DeviceEventEmitter 监听广播 应用场景: - 表单提交页面, A页面跳转到B页面选人, 然后返回A页面, 需要将B页面选择的数据传回A页面. - 多个多媒体来回切换播放,暂停后二次继续播放等问题. 代码如下: A页面 componentDidMount() { // 利用DeviceEventEmitter 监听 concactAdd事件 this.subscription = DeviceEventEmitter.addListener

  • react-native使用react-navigation进行页面跳转导航的示例

    首先要确认已经配置好react-native的环境. # 创建一个native应用,SimpleApp,然后进入项目目录 react-native init SimpleApp cd SimpleApp # 通过npm安装最新版本的react-navigation npm install --save react-navigation # 运行程序 react-native run-android 引入Stack Navigator 对于我们的应用程序,我们想要使用堆栈式导航器,因为我们想要一个

  • React Native 加载H5页面的实现方法

    目录 一.基本使用 1.1 RN向H5发送数据 1.2 H5向RN传递数据 1.3 双向传值 二.属性和方法 2.1 属性 2.2 方法 三.使用示例 3.1 加载外源网页信息 3.2 登陆场景 3.3 功能模块嵌入到 RN 中 3.4 完整示例 一.基本使用 作为目前流行的移动跨平台开发技术,React Native 提供了一个使用 JavaScript 构建原生跨平台移动应用的强大框架.使用React Native开发时,经常会遇到加载H5网页的需求,此时需要用到react-native-w

  • Android仿微信加载H5页面进度条

    前言 Android中WebView打卡前端页面时受到网路环境,页面内容大小的影响有时候会让用户等待很久.显示一个加载进度条可以提升很大的体验.微信内访问H5页面加载效果不错,效仿着写了一个. 1.实现 1-1.自定义类继承WebView类 class ProgressWebView(context: Context, attr: AttributeSet) : WebView(context, attr) { /** *xml布局中使用,所以用两个构造参数的构造函数 */ private va

  • React Native 真机断点调试+跨域资源加载出错问题的解决方法

    写在前面 闲来无事,折腾了一下React Native,相比之前,开发体验好了不少.但在真机断点调试那里遇到了跨域资源加载出错的问题,一番探索总算解决,目测是RN新版本调试服务的bug. 遇到类似问题的同学应该不少,这里做下记录,有需要的可以参考下. 如何断点调试 首先,在真机上加载运行RN应用(过程略). 然后,摇动手机,弹出开发菜单,选择"Debug JS Remotely". chrome会自动打开调试界面,地址是 http://localhost:8081/debugger-u

  • android 关于webview 加载h5网页开启定位的方法

    如下所示: //webview定位相关设置 settings.setDomStorageEnabled(true); settings.setGeolocationEnabled(true); //settings.setGeolocationDatabasePath(getFilesDir().getPath()); progressWebView.setWebChromeClient(new WebChromeClient() { @Override public void onGeoloc

  • React 首页加载慢问题性能优化案例详解

    学习了一段时间React,想真实的实践一下.于是便把我的个人博客网站进行了重构.花了大概一周多时间,网站倒是重构的比较成功,但是一上线啊,那个访问速度啊,是真心慢,慢到自己都不能忍受,那么小一个网站,没几篇文章,慢成那样,不能接受.我不是一个追求完美的人,但这样可不行.后面大概花了一点时间进行性能的研究.才发现慢是有原因的. React这类框架? 目前主流的前端框架React.Vue.Angular都是采用客户端渲染(服务端渲染暂时不在本文的考虑范围内).这当然极大的减轻了服务器的压力.相对的浏

  • Android webview加载H5方法详细介绍

    目录 1,安卓APP 怎么用webview加载H5 2,H5怎么调用安卓定义的方法 3,安卓怎么调用H5定义的方法 这篇文章主要阐述3个知识点 安卓APP 怎么用webview加载H5 H5怎么调用安卓定义的方法 安卓怎么调用H5定义的方法 1,安卓APP 怎么用webview加载H5 安卓端定义个webview xml 页面,代码如下所示: <?xml version="1.0" encoding="utf-8"?> <WebView xmlns

  • React懒加载实现原理深入分析

    目录 1.代码分割 2.React的懒加载 import() 原理 React.lazy 原理 Suspense 原理 小结 1.代码分割 (1)为什么要进行代码分割? 现在前端项目基本都采用打包技术,比如 Webpack,JS逻辑代码打包后会产生一个 bundle.js 文件,而随着我们引用的第三方库越来越多或业务逻辑代码越来越复杂,相应打包好的 bundle.js 文件体积就会越来越大,因为需要先请求加载资源之后,才会渲染页面,这就会严重影响到页面的首屏加载. 而为了解决这样的问题,避免大体

  • jQuery模拟原生态App上拉刷新下拉加载更多页面及原理

    很多App中,新闻或者展示类都存在下拉刷新和上拉加载的效果,网上提供了实现这种效果的第三方类(详情请见MJRefresh和EGOTableViewPullRefresh),用起来很方便,但是闲暇之余,我们可以思考下,这种效果实现的原理是什么,我以前说过,只要是动画都是骗人的,只要不是硬件问题大部分效果都能在系统UI的基础上做出来. 下面通过jQuery手机端上拉下拉刷新页面代码,很像QQ空间客户端或者微信下拉刷新页面特效代码. 请看下面效果图: 在线预览    源码下载 html代码: <div

  • jQuery页面加载初始化的3种方法(推荐)

    jQuery 页面加载初始化的方法有3种 ,页面在加载的时候都会执行脚本,应该没什么区别,主要看习惯吧,本人觉得第二种方法最好,比较简洁. 第一种: $(document).ready(function(){ alert("第一种方法."); }); 第二种: $(function(){ alert("第二种方法."); });  第三种: jQuery(function($) { alert("第三种方法."); }); ps; 不用jQuer

  • Js Jquery创建一个弹出层可加载一个页面

    复制代码 代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"

随机推荐