一、基本使用

作为目前流行的移动跨平台开发技术,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页面内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

React Native 加载H5页面的实现方法的更多相关文章

  1. ios – React native链接到另一个应用程序

    如果是错误的,有人知道如何调用正确的吗?

  2. ios – React Native – 在异步操作后导航

    我正在使用ReactNative和Redux开发移动应用程序,我正面临着软件设计问题.我想调用RESTAPI进行登录,如果该操作成功,则导航到主视图.我正在使用redux和thunk所以我已经实现了异步操作,所以我的主要疑问是:我应该把逻辑导航到主视图?我可以直接从动作访问导航器对象并在那里执行导航吗?.我对组件中的逻辑没有信心.似乎不是一个好习惯.有没有其他方法可以做到这一点?

  3. 在ios中使用带有React Native(0.43.4)的cocoapods的正确方法是什么?

    我已经挖掘了很多帖子试图使用cocoapods为本地ios库设置一个反应原生项目,但我不可避免地在#import中找到了丢失文件的错误.我的AppDelegate.m文件中的语句.什么是使用反应原生的可可豆荚的正确方法?在这篇文章发表时,我目前的RN版本是0.43.4,而我正在使用Xcode8.2.1.这是我的过程,好奇我可能会出错:1)

  4. ios – React Native WebView滚动行为无法按预期工作

    如何确保滚动事件的行为与ReactNative应用程序中的浏览器相同?

  5. ios – React Native – BVLinearGradient – 找不到’React/RCTViewManager.h’文件

    谢谢.解决方法几天前我遇到了完全相同的问题.问题是在构建应用程序时React尚未链接.试试这个:转到Product=>Scheme=>管理方案…=>点击你的应用程序Scheme,然后点击Edit=>转到Build选项卡=>取消选中ParallelizeBuild然后点击标志添加目标=>搜索React,选择第一个名为React的目标,然后单击Add然后在目标列表中选择React并将其向上拖动到该列表中的第一个.然后转到Product=>再次清理并构建项目.这应该有所帮助.

  6. ios – React Native – NSNumber无法转换为NSString

    解决方法在你的fontWeight()函数中也许变成:

  7. ios – React native error – react-native-xcode.sh:line 45:react-native:command not found命令/ bin/sh失败,退出代码127

    尝试构建任何(新的或旧的)项目时出现此错误.我的节点是版本4.2.1,react-native是版本0.1.7.我看过其他有相同问题的人,所以我已经更新了本机的最新版本,但是我仍然无法通过xcode构建任何项目.解决方法要解决此问题,请使用以下步骤:>使用节点版本v4.2.1>cd进入[你的应用]/node_modules/react-native/packager>$sh./packager.s

  8. 反应原生 – 如何通过Xcode构建React Native iOS应用程序到设备?

    我试图将AwesomeProject应用程序构建到设备上.构建成功并启动屏幕显示,但后来我看到一个红色的“无法连接到开发服务器”屏幕.它表示“确保节点服务器正在运行–从Reactroot运行”npmstart“.看起来节点服务器已经运行,因为当我做npm启动时,我收到一个EADDRINUSE消息,表示该端口已经在使用.解决方法从设备访问开发服务器您可以使用开发服务器快速迭代设备.要做到这一点,你的

  9. 静音iOS推送通知与React Native应用程序在后台

    我有一个ReactNative应用程序,我试图获得一个发送到JavaScript处理程序的静默iOS推送通知.我看到的行为是AppDelegate中的didReceiveRemoteNotification函数被调用,但是我的JavaScript中的处理程序不会被调用,除非应用程序在前台,或者最近才被关闭.我很困惑的事情显然是应用程序正在被唤醒,并且它的didReceiveRemoteNotifi

  10. 如何为iOS的React Native设置分析

    所以我已经完成了一个针对iOS的ReactNative项目,但是我想在其中分析.我尝试了react-native-google-analytics软件包,但是问题阻止了它的正常工作.此外,react-native-cordova-plugin软件包只适用于Android,因此插入Cordova插件进行分析的能力现在已成为问题.我也没有Swift/ObjectiveC的经验,所以将完全失去GA的插入.有没有人有任何建议如何连接GoogleAnalytics的ReactNativeforiOS?

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部