重构 AutoHeightWebView 库以获取在单独的浏览器中打开的超链接

2024-03-27

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

我一直在尝试重复这个过程,以便我们能够得到相同的行为。所以我将这段代码添加到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 })
);

但这没有任何作用。

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

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] /cdn-cgi/l/email-protection并制作另一个补丁包,因为该版本与React Native 60s版本控制不兼容,即我们不再使用index.ios.js/index.android.js但反而index.js.

最早的包react-native-autoheight-webview将是 1.0.0 并且该版本没有实际意义,因为WebView and Linking模块不再在react-native图书馆,但里面react-native-webview库,它看起来并不支持相同的属性来让用户在单独的浏览器中打开超链接,而不是在应用程序的 Web 视图中打开超链接。至少我的尝试没有成功。

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

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 端,我收到此错误:

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 通信,成功指示我的应用程序在外部浏览器中打开外部链接?

我在 `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 https://medium.com/@elhardoum/opening-external-links-in-browser-in-react-native-webview-18fe6a66312a

它对我没有任何作用。

接下来我尝试添加onNavigationStateChange财产归我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"}
      />

新闻文章从未完成加载。


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

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

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

无需应用任何补丁或其他东西,您可以简单地将react-native-autoheight-webview与react-native-webview一起使用。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

重构 AutoHeightWebView 库以获取在单独的浏览器中打开的超链接 的相关文章

随机推荐