react-native WebView 返回处理方法

项目中有些页面内容是变更比较频繁的,这些页面我们会考虑用 网页 来解决。

在RN项目中提供一个公用的Web页,如果是网页内容,就跳转到这个界面展示。

此时会有一个问题是,网页会有一级页面,二级页面,这就会设计到导航栏返回键的处理(以及在Android上返回键的处理)。

这个问题,在RN官网就可找到解决方式。就是用 onNavigationStateChange 这个回调方法记录当前的导航状态,从而判断是返回上一级页面还是退出这个网页,回到App的其他界面。

但是,当网页的实现是React时,就会有问题了,你会发现,当页面跳转的时候,onNavigationStateChange这个回调方法没有回调!!!怎么肥四!!

一开始尝试了把网页地址换成百度的,可以接收回调,一切都运行的很好,可是换成我们的链接就不行,所以就把锅甩给了后台,以为是React哪边写的不对。

因为上一个项目时间紧,没有时间好好去看一下源码,就想了一个不是很完善的解决方案,就是网页用js来回调App来告知现在的导航状态,这样的解决方式显示是不友好的。

现在稍微有点时间看了源码才知道真正原因。

下面就分析一下这个问题的原因和我的解决方式。

1.首先,先找到源码的位置。

node_moduleseact-nativeReactAndroidsrcmainjavacomacebookeactiewswebview

node_moduleseact-nativeLibrariesComponentsWebView

目录结构是这样的:

react-native WebView 返回处理方法 

react-native WebView 返回处理方法

2.实现的代码段 (JAVA端)

RN的实际运行代码都是原生代码,所以,像WebView组件的一些事件回调,其实都是原生代码中的回调触发的。如下

(ReactWebViewManager.java) rn版本0.47.1

protected static class ReactWebViewClient extends WebViewClient { //WebViewClient就是我们在写Android原生代码时,监听网页加载情况使用的工具。   protected static final String REACT_CLASS = "RCTWebView"; //定义的原生组件名,在后面JS中会对应到。  //...  @Override  public void onPageStarted(WebView webView, String url, Bitmap favicon) { //有很多回调方法,此处只举一例   super.onPageStarted(webView, url, favicon);   mLastLoadFailed = false;   dispatchEvent(     webView,     new TopLoadingStartEvent(   //自己定义的时间,dispatch后,事件会传给js       webView.getId(),       createWebViewEvent(webView, url)));  }  //... }

登录后复制

(ReactWebViewManager.java) rn版本0.43.3  ,RN不同版本会有代码调整,所以RN升级的时候,需要仔细的回归测试。

protected static class ReactWebViewClient extends WebViewClient { //WebViewClient就是我们在写Android原生代码时,监听网页加载情况使用的工具。   protected static final String REACT_CLASS = "RCTWebView"; //定义的原生组件名,在后面JS中会对应到。  //...  @Override  public void onPageStarted(WebView webView, String url, Bitmap favicon) { //有很多回调方法,此处只举一例   super.onPageStarted(webView, url, favicon);   mLastLoadFailed = false;   dispatchEvent(     webView,     new TopLoadingStartEvent(   //自己定义的时间,dispatch后,事件会传给js       webView.getId(),       createWebViewEvent(webView, url)));  }  @Override  public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload) { //坑在这,这里就是导航有变化的时候会回调在这个版本是有这个处理的,但是不知道在哪个版本删掉了 -.-   super.doUpdateVisitedHistory(webView, url, isReload);   dispatchEvent(     webView,     new TopLoadingStartEvent(       webView.getId(),       createWebViewEvent(webView, url)));  }  //... }

登录后复制

(TopLoadingStartEvent.java) 回调JS的Event

public class TopLoadingStartEvent extends Event { public static final String EVENT_NAME = "topLoadingStart";  //对应方法是onLoadingStart, 因为对RN的结构不熟悉,在此处花了很长时间研究是怎么对应的,最后找到了定义对应的文件 private WritableMap mEventData; public TopLoadingStartEvent(int viewId, WritableMap eventData) {  super(viewId);  mEventData = eventData; } @Override public String getEventName() {  return EVENT_NAME; } @Override public boolean canCoalesce() {  return false; } @Override public short getCoalescingKey() {  // All events for a given view can be coalesced.  return 0; } @Override public void dispatch(RCTEventEmitter rctEventEmitter) {  rctEventEmitter.receiveEvent(getViewTag(), getEventName(), mEventData); }}

登录后复制

(node_moduleseact-nativeReactAndroidsrcmainjavacomacebookeactuimanagerUIManagerModuleConstants.java)

这个文件里,定义了对应关系

/** * Constants exposed to JS from {@link UIManagerModule}. *//* package */ class UIManagerModuleConstants { /* package */ static Map getDirectEventTypeConstants() {  return MapBuilder.builder()    .put("topContentSizeChange", MapBuilder.of("registrationName", "onContentSizeChange"))    .put("topLayout", MapBuilder.of("registrationName", "onLayout"))    .put("topLoadingError", MapBuilder.of("registrationName", "onLoadingError"))    .put("topLoadingFinish", MapBuilder.of("registrationName", "onLoadingFinish"))    .put("topLoadingStart", MapBuilder.of("registrationName", "onLoadingStart"))    .put("topSelectionChange", MapBuilder.of("registrationName", "onSelectionChange"))    .put("topMessage", MapBuilder.of("registrationName", "onMessage"))    .build(); }}

登录后复制

3.实现的代码段 (JS端)

(node_moduleseact-nativeLibrariesComponentsWebViewWebView.android.js)

在下面的代码中可以看到只有 onLoadingStart    和 onLoadingFinish 才会调用  updateNavigationState ,问题就出现在这了,由于我们的网页实现是React,只有一个页面啊!所以只会调用一次 onLoadingStart  和 onLoadingFinish 。再点击详情页并不会跳转到新页面,而是刷新原来的页面。所以也就没有 updateNavigationState 回调了。

class WebView extends React.Component { static propTypes = {  //给外部定义的可设置的属性  ...ViewPropTypes,  renderError: PropTypes.func,  renderLoading: PropTypes.func,  onLoad: PropTypes.func,  //...  } render() { //绘制页面内容  //...  var webView =   ;  return (       {webView}    {otherView}     ); } onLoadingStart = (event) => {  var onLoadStart = this.props.onLoadStart;  onLoadStart && onLoadStart(event);  this.updateNavigationState(event); }; onLoadingFinish = (event) => {  var {onLoad, onLoadEnd} = this.props;  onLoad && onLoad(event);  onLoadEnd && onLoadEnd(event);  this.setState({   viewState: WebViewState.IDLE,  });  this.updateNavigationState(event); }; updateNavigationState = (event) => {  if (this.props.onNavigationStateChange) {   this.props.onNavigationStateChange(event.nativeEvent);  } };}var RCTWebView = requireNativeComponent('RCTWebView', WebView, {  //对应上面JAVA中的 ‘RCTWebView' nativeOnly: { messagingEnabled: PropTypes.bool, }, }); module.exports = WebView;

登录后复制

2.解决方法

既然原因找到了,就容易解决了

解决方式:自定义WebView,添加 doUpdateVisitedHistory 处理,在每次导航变化的时候,通知JS。

1. 拷贝下图中的文件到我们自己项目中的Android代码目录下

react-native WebView 返回处理方法

拷贝完后的Android目录:

react-native WebView 返回处理方法

ReactWebViewManager.java中需要修改几个地方

public class ReactWebViewManager extends SimpleViewManager { protected static final String REACT_CLASS = "RCTWebView1"; //此处修改一下名字 protected static class ReactWebViewClient extends WebViewClient {    @Override    public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload) {      super.doUpdateVisitedHistory(webView, url, isReload);      dispatchEvent(    //在导航变化的时候,dispatchEvent          webView,          new TopCanGoBackEvent(              webView.getId(),              createCanGoBackWebViewEvent(webView, url)));    } }}

登录后复制

TopCanGoBackEvent是我自己添加的一个Event,专门用来通知导航变化

TopCanGoBackEvent.java

public class TopCanGoBackEvent extends Event { public static final String EVENT_NAME = "topChange";  private WritableMap mEventData; public TopCanGoBackEvent(int viewId, WritableMap eventData) {  super(viewId);  mEventData = eventData; } @Override public String getEventName() {  return EVENT_NAME; } @Override public boolean canCoalesce() {  return false; } @Override public short getCoalescingKey() {  // All events for a given view can be coalesced.  return 0; } @Override public void dispatch(RCTEventEmitter rctEventEmitter) {  rctEventEmitter.receiveEvent(getViewTag(), getEventName(), mEventData); }}

登录后复制

新建 ReactWebViewPage.java

public class ReactWebViewPackage implements ReactPackage {  @Override  public List createNativeModules(ReactApplicationContext reactContext) {    return Collections.emptyList();  }  @Override  public List createViewManagers(ReactApplicationContext reactContext) {    return Arrays.asList(        new ReactWebViewManager()    );  }}

登录后复制

然后在MainApplication中添加这个模块

public class MainApplication extends Application implements ReactApplication {  @Override  protected List getPackages() {   return Arrays.asList(     new MainReactPackage(),     new ReactWebViewPackage()  //WebView   );  }}

登录后复制

以上就是Android需要修改的地方,ios我没有尝试过,应该大差不差同一个道理。

2. 拷贝下图中的文件到我们自己项目中的JS代码目录下,并修改一下名字

react-native WebView 返回处理方法

JS代码目录:

react-native WebView 返回处理方法

CustomWebView.android.js 有几个地方需要修改。

/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule CustomWebView  //此处需要修改名称 */var RCT_WEBVIEW_REF = 'webview1'; //此处需要修改名称 render() {  var webView =   ;  return (       {webView}    {otherView}     ); } onChange = (event) => {  //添加方法  this.updateNavigationState(event); };}var RCTWebView = requireNativeComponent('RCTWebView1', CustomWebView, CustomWebView.extraNativeComponentConfig); //修改名称module.exports = CustomWebView; //修改名称

登录后复制

至此就完成自定义WebView模块。也可以解决网页是React实现,不能导航的问题。

以上就是react-native WebView 返回处理方法的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2785501.html

(0)
上一篇 2025年3月8日 17:27:00
下一篇 2025年3月8日 17:27:08

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • web端实现后退强制刷新功能代码

    本文主要和大家介绍了微信web端后退强制刷新功能的实现代码,需要的朋友可以参考下,希望能帮助到大家。 具体代码如下所示: //生成uuid var uuidChars = “0123456789ABCDEFGHIJKLMNOPQRSTUVW…

    编程技术 2025年3月8日
    200
  • JS和WebService大文件上传代码分享

    在编写前端的过程中,难免会遇到文件上传的问题,当用户要上传较大的文件是,会被服务器端限制,阻止其上传,在asp.net中,调整服务器接受文件的大小的配置方法如下:  在ASP中配置Web.config文件的httpRuntime: 登录后复…

    编程技术 2025年3月8日
    200
  • web.xml的配置

    这次给大家带来web.xml的配置,web.xml配置注意事项有哪些,下面就是实战案例,一起来看一下。 nbsp;web-app PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application …

    编程技术 2025年3月8日
    200
  • webpack打包之后的文件过大如何解决

    本文主要和大家介绍了webpack打包之后的文件过大的解决方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能帮助到大家。 以前一直使用 create-react-app 这个脚手架进行 react 开发…

    2025年3月8日
    200
  • 常用的WebStorm快捷键

    这次给大家带来常用的webstorm快捷键,使用webstorm快捷键的注意事项有哪些,下面就是实战案例,一起来看一下。 如何在WebStorm中利用快捷键创建一个新的.html的文件 同时按下键盘上的Ctrl + Alt + Insert…

    编程技术 2025年3月8日
    200
  • webpack如何打包js

    webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。本文主要和大家介绍了webpack打包js的方法,在代码实践之前,先说一写webpack的基础知识。 1、为什…

    2025年3月8日
    200
  • webpack的使用详解

    这次给大家带来webpack的使用详解,使用webpack的注意事项有哪些,下面就是实战案例,一起来看一下。 1.安装 //全局安装npm install -g webpack//安装到你的项目目录npm install –save-de…

    编程技术 2025年3月8日
    200
  • 怎样用webpack写jquery的环境配置

    这次给大家带来怎样用webpack写jquery的环境配置,用webpack写jquery环境配置的注意事项有哪些,下面就是实战案例,一起来看一下。 客户需求要一个具备树结构、带复选框的下拉选择控件;在网上找到了select2、autoco…

    2025年3月8日
    200
  • nodejs如何实现的简单web服务器功能

    本文主要和大家介绍了nodejs实现的简单web服务器功能,结合实例形式分析了nodejs构建web服务器的相关监听、响应、数据处理等操作技巧,需要的朋友可以参考下,希望能帮助到大家。 前端js代码: $.ajax({ url:'…

    编程技术 2025年3月8日
    200
  • WebSocketSharp的IM实现

    这次给大家带来WebSocketSharp的IM实现,WebSocketSharp的IM实现注意事项有哪些,下面就是实战案例,一起来看一下。 websocket-sharp 是一个websocket的C#实现,支持.net 3.5及以上来开…

    2025年3月8日 编程技术
    200

发表回复

登录后才能评论