本文介绍了重构 AutoHeightWebView 库以获取在单独的浏览器中打开的超链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个升级的 React Native 应用程序.回到旧版时,如果您转到新闻文章并且该文章有超链接并且您单击超链接,它会将您重定向到您的手机浏览器并在那里打开链接,但它不再这样做,因为我们必须升级react-native-autoheight-webview 库,因此为 0.6.1 版本所做的补丁现已消失.该补丁允许在单独的浏览器中打开超链接.

I have a React Native application that I upgraded. Back when it was legacy, if you went to a news article and the article had hyperlinks and you clicked on the hyperlinks it would redirect you to your phones browser and open the link there, but it no longer does that because we had to upgrade the react-native-autoheight-webview library, so the patch that was done for the 0.6.1 version is now gone. That patch is what allowed hyperlinks to open in a separate browser.

我一直在尝试重复该过程,以便我们获得相同的行为.所以我将此代码添加到 node_modules/react-native-autoheight-webview/AutoHeightWebView/index.js 文件:

I have been trying to repeat the process so we can get the same behavior. So I added this code to node_modules/react-native-autoheight-webview/AutoHeightWebView/index.js file:

const _onLoadStart = event => {
    if (event.nativeEvent.url.startsWith("http")) {
        this.stopLoading();
        Linking.openURL(event.nativeEvent.url).catch(err => console.log('An error occurred', err));
    } else {
        const {onLoadStart} = this.props;
        onLoadStart && onLoadStart(event);
    }
  }

    const { currentSource, script } = reduceData(props);

    const { width, height } = size;
    useEffect(
      () =>
        onSizeUpdated &&
        onSizeUpdated({
          height,
          width
        }),
      [width, height, onSizeUpdated]
    );



    return (
      <WebView
        {...props}
        ref={webView}
        onMessage={handleMessage}
        onLoadStart={_onLoadStart}
        style={[
          styles.webView,
          {
            width,
            height
          },
          style
        ]}
        injectedJavaScript={script}
        source={currentSource}
      />
    );
  }),
  (prevProps, nextProps) => !shouldUpdate({ prevProps, nextProps })
);

但这没有任何作用.

我也在同一个文件中尝试过:

I also tried this in the same file:

const uri = `${media}/1.0/articles`;

    return (
      <WebView
        {...props}
        ref={webView}
        onMessage={handleMessage}
        source={{uri}}
        onNavigationStateChange={(event) => {
          if (event.url !== uri) {
            this.webview.stopLoading();
            Linking.openURL(event.url);
          }
        }}
        style={[
          styles.webView,
          {
            width,
            height
          },
          style
        ]}
        injectedJavaScript={script}
        source={currentSource}
      />
    );

什么都没有.

我不能回到 [email protected] 并做另一个补丁包,因为那个版本与 React Native 60s 版本不兼容,即我们不再使用 index.ios.js/index.android.js 而是 index.js.

I cannot go back to [email protected] and do another patch package because that version is incompatible with React Native 60s versioning, namely we no longer use index.ios.js/index.android.js but instead index.js.

react-native-autoheight-webview 最早的包是 1.0.0 并且它在那个版本中没有实际意义,因为 WebViewLinking 模块不再在 react-native 库中,而是在 react-native-webview 库中,它看起来不像支持相同的属性让用户在单独的浏览器中打开超链接,而不是在应用程序的 web 视图中.至少我一直没有成功.

The earliest package of react-native-autoheight-webview would be 1.0.0 and its a moot point by that version because the WebView and Linking module are no longer in the react-native library, but inside of react-native-webview library and it doesn't look like it supports the same properties to get a user to open a hyperlink in a separate browser as opposed to within the webview of the application. At least I have been unsuccessful in trying.

我还尝试了一个免费包 react-native-webview-bridge 来解决这个问题,但该包开始使我的应用程序在 iOS 和 Android 端崩溃,所以这不是一个可行的解决方案.以下是该方法如何失败的几个示例:

I also tried a complimentary package react-native-webview-bridge to come to the rescue but that package began crashing my application on both the iOS and Android side, so that was not a viable solution. Here are a couple of examples of how this approach failed:

Undefined symbols for architecture arm64:
  "_RCTJSNavigationScheme", referenced from:
      -[RCTWebViewBridgeManager constantsToExport] in libReact-Native-Webview-Bridge.a(RCTWebViewBridgeManager.o)
      -[RCTWebViewBridge webView:shouldStartLoadWithRequest:navigationType:] in libReact-Native-Webview-Bridge.a(RCTWebViewBridge.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

在 iOS 端,在 Android 端我收到这个错误:

on the iOS side, on the Android side I got this error:

2019-10-17 13:01:14.292 15725-15839/com.nfibengage.dv E/AndroidRuntime: FATAL EXCEPTION: mqt_native_modules
    Process: com.nfibengage.dv, PID: 15725
    java.lang.NoClassDefFoundError: Failed resolution of: Lcom/facebook/react/views/webv

我想归根结底,我如何通过从 DOM 与 React Native 通信来成功指示我的应用在外部浏览器中打开外部链接?

I guess at the end of the day, how do I successfully instruct my app to open an external link in an outside browser via communicating with React Native from the DOM?

我在 `node_modules/react-native-autoheight-webview/AutoHeightWebView/index.js 中尝试了这个配置:

I tried this configuration inside of `node_modules/react-native-autoheight-webview/AutoHeightWebView/index.js:

jsCode = () => {
   const attachEvent = function(elem, event, callback) {
     event = event.replace(/^on/g, '');
     if ('addEventListener' in window) {
       elem.addEventListener(event, callback, false);
     } else if ('attachEvent' in window) {
       elem.attachEvent('on' + event, callback);
     } else {
       const registered = elem['on' + event];
       elem['on' + event] = registered ? function(e) {
         registered(e);
         callback(e);
       } : callback;
     }

     return elem;
   }

   const all_links = document.querySelectorAll('a[href]');

   if (all_links) {
     for (var i in all_links) {
       if (all_links.hasOwnProperty(i)) {
         attachEvent(all_links[i], 'onclick', function(e) {
           if (!new RegExp('^https?:\/\/' + location.host, 'gi').test(this.href)) {
             // handle external URL
             e.preventDefault();

             window.postMessage(JSON.stringify({
               external_url_open: this.href
             }));
           }
         });
       }
     }
   }
 }



 render() {
   const { height, width } = this.state;
   const { style, originWhitelist } = this.props;
   const { source, script } = this.getUpdatedState(this.props, getBaseScript);
   return (
     <WebView
       {...this.props}
       originWhitelist={originWhitelist || ['*']}
       ref={this.webView}
       onMessage={this.onMessage}
       style={[
         styles.webView,
         {
           width,
           height
         },
         style
       ]}
       injectedJavaScript={this.jsCode}
       source={source}
     />
   );
 }
}

使用本文档作为指南:https://medium.com/@elhardoum/opening-external-links-in-browser-in-react-native-webview-18fe6a66312a

它对我没有任何作用.

接下来,我尝试将 onNavigationStateChange 属性添加到我的 ActionAlertFeedCard:

Next I tried adding the onNavigationStateChange property to my ActionAlertFeedCard:

import React from "react";
import {
  Text,
  StyleSheet,
  View,
  TouchableOpacity,
  Platform
} from "react-native";
import { WebView } from "react-native-webview";
import { TextButton } from "react-native-material-buttons";
import PropTypes from "prop-types";
import format from "date-fns/format";
import { Card, Divider } from "common-components";
import { v2Colors, feedContentStyles, v2ButtonStyles } from "theme";
import { moderateScale } from "react-native-size-matters";

//prettier-ignore
const getHtml = content => `<body style="font-family: -apple-system, Roboto, sans-serif; font-size: ${moderateScale(32, 0.2)}px;">${content}</body>`;

const ActionAlertFeedCard = ({
  completed,
  content,
  datePosted,
  mainActionButtonPress,
  secondaryActionButtonPress,
  style,
  title
}) => (
  <Card style={style}>
    <View style={feedContentStyles.header}>
      <Text style={feedContentStyles.title}>{"ACTION ALERT"}</Text>
      <Text style={feedContentStyles.postDate}>
        {`${completed ? "Completed" : "Posted"} ${format(
          datePosted,
          "MMM D, YYYY"
        )}`}
      </Text>
    </View>
    <Divider />
    <View style={feedContentStyles.content}>
      <Text style={feedContentStyles.contentTitle}>{title}</Text>
      <WebView
        useWebKit={true}
        scrollEnabled={false}
        style={styles.webview}
        source={{
          html: getHtml(content)
        }}
        onNavigationStateChange={event => {
          console.log("url of webpage" + event.url);
        }}
        // scalesPageToFit={Platform.OS !== "ios"}
      />

新闻文章从未完成加载.

The news articles never completed loading up.

推荐答案

如果您希望所有超链接都在外部浏览器中打开,那么您尝试过的这种方法应该可行:

If you want all hyperlinks to open in external browser then this method which you've tried should work:

onNavigationStateChange={(event) => {
     console.log("url of webpage: "+ event.url);
          if (event.url !== uri) {
            this.webview.stopLoading();
            Linking.openURL(event.url);
          }
        }}

其中 uri 是您最初加载的文章的网址.如果它不起作用,请尝试保留控制台日志并检查该事件是否被触发.

where uri is url of the article which you are loading initially. If it's not working then try keeping console log and check if that event is being fired or not.

不需要应用任何补丁什么的,你可以简单地使用 react-native-autoheight-webview 和 react-native-webview.

There is no need to apply any patch or something, you can simple use react-native-autoheight-webview with react-native-webview.

webview 库页面上有关于此的指南:https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#controlling-navigation-state-changes

There is guide about this on webview library page: https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#controlling-navigation-state-changes

这篇关于重构 AutoHeightWebView 库以获取在单独的浏览器中打开的超链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 04:49