Подтвердить что ты не робот

React Native - открыть ссылки в браузере

Привет, я использую интерактивный веб-просмотр, чтобы отобразить некоторые html, я хочу, чтобы всякий раз, когда пользователь щелкает ссылку внутри этого html, он откроет браузер пользователя с этой ссылкой.

возможно?

Изменить 1:

В итоге я использовал этот пакет: npmjs.com/package/react-native-communications, который открывает браузер. Я вызываю браузер для открытия onNavigationStateChange при изменении URL-адреса.

Теперь дело в том, что WebView продолжает обрабатывать запрос, хотя я переехал в браузер, как я могу остановить запрос?

4b9b3361

Ответ 1

Вот полное рабочее решение:

import React, { Component } from 'react';
import { WebView, Linking } from 'react-native';

export default class WebViewThatOpensLinksInNavigator extends Component {
  render() {
    const uri = 'http://stackoverflow.com/questions/35531679/react-native-open-links-in-browser';
    return (
      <WebView
        ref={(ref) => { this.webview = ref; }}
        source={{ uri }}
        onNavigationStateChange={(event) => {
          if (event.url !== uri) {
            this.webview.stopLoading();
            Linking.openURL(event.url);
          }
        }}
      />
    );
  }
}

Он использует простой WebView, перехватывает любое изменение URL и, если этот URL отличается от исходного, останавливает загрузку, предотвращает изменение страницы и открывает ее в OS Navigator.

ios simulator

Ответ 3

Это мое решение. Поскольку он не является общим, вы можете улучшить введенный javascript в соответствии с вашими требованиями.

import {
  View,
  WebView,
  Linking,
} from 'react-native';

const injectScript = `
  (function () {
    window.onclick = function(e) {
      e.preventDefault();
      window.postMessage(e.target.href);
      e.stopPropagation()
    }
  }());
`;

class MyWebView extends React.Component {

  onMessage({ nativeEvent }) {
    const data = nativeEvent.data;

    if (data !== undefined && data !== null) {
      Linking.openURL(data);
    }
  }

  render() {
    return (
      <WebView
        source={{ html: this.props.html }}
        injectedJavaScript={injectScript}
        onMessage={this.onMessage}
      />
    )
  }
}

Ответ 4

Большая проблема с использованием "stopLoading()" заключается в том, что в Android он отключает дальнейшие нажатия на любые другие ссылки с этой исходной страницы.

Компонент WebView выделяется из ядра RN и в руки сообщества. Если вместо этого вы используете эту версию (https://github.com/react-native-community/react-native-webview), вы можете использовать опору "onShouldStartLoadWithRequest" на iOS и Android, что делает ее намного более элегантной.

Построение Дэмиена Варрона действительно полезный ответ, вот пример того, как вы могли бы использовать этот реквизит, чтобы избежать stopLoading, который работает кроссплатформенно:

onShouldStartLoadWithRequest={event => {
    if (event.url !== uri) {
        Linking.openURL(event.url)
        return false
    }
    return true
}}

А вот как вы можете это сделать, если вашим источником является HTML, а не URI:

onShouldStartLoadWithRequest={event => {
    if (event.url.slice(0,4) === 'http') {
        Linking.openURL(event.url)
        return false
    }
    return true
}}

Как указал basbase, вы также можете сделать это следующим образом (я добавил раздел about: blank). Я планирую проб и ошибок больше, чтобы увидеть, какие из них лучше.

onShouldStartLoadWithRequest={event => {
    if (!/^[data:text, about:blank]/.test(event.url)) {
        Linking.openURL(event.url)
        return false
    }
    return true
}}

Ответ 5

Я нашел способ сделать это, хотя это решение для iOS!

Вот пошаговые инструкции:

  1. Свяжите библиотеку 'RCTLinkingIOS' с вашим проектом. Я использовал CocoaPods, чтобы так.
  2. В вашем WebView добавьте "onShouldStartLoadWithRequest". Например

    <WebView source={{ html: content }} onShouldStartLoadWithRequest={this.onShouldStartLoadWithRequest}/>

  3. Добавьте функцию this.onShouldStartLoadWithRequest. Верните TRUE или FALSE в зависимости от того, хотите ли вы перейти по ссылке в вашем WebView. Это в основном эквивалент реализации UIWebViewDelegate, которую вы использовали бы при реализации в нативном коде (Swift или Objective-C).

    onShouldStartLoadWithRequest = (event) => {
         Linking.canOpenURL(event.url).then(supported => {
             if (supported) {
                 Linking.openURL(event.url);
             } else {
                 console.log('Don\'t know how to open URI: ' + event.url);
             }
             return false
         });
    }
    
  4. Убедитесь, что вы также импортировали Linking в ваш источник JavaScript:

    import { AppRegistry, View, WebView, Linking } from 'react-native';

Это должно делать свое дело.

Для получения дополнительной информации см. Собственные документы по реагированию: https://facebook.github.io/react-native/docs/linking.html.

Ответ 7

Это можно сделать кросс-платформенным способом, используя встроенный класс Linking и react-native-webview-bridge.

const generateLink = (text, url) => {
  if (url) {
    return `<a href='#' onclick='WebViewBridge.send("${url}"); return false;'>${text}</a>`;
  } else {
    return text;
  }
};

const generateHtml = () => `<!DOCTYPE html><html><body>
  ${generateLink('Link text', 'http://example.com')}
</body></html>`;

С компонентом WebViewBridge, созданным следующим образом:

<WebViewBridge
  javaScriptEnabled
  renderLoading={() => <ActivityIndicator animating size="large" />}
  source={{ html: generateHtml() }}
  onBridgeMessage={url => Linking.openURL(url)}
/>

Ответ 8

В дополнение к отличному ответу fooobar.com/questions/240486/...: При использовании source={{html: '...'}} вы можете проверить изменение внешнего URL-адреса с помощью: if (!/^data:text/.test(event.url)) {

Ответ 9

Если stopLoading() в onNavigationStateChange на Android не работает,

this.webview.stopLoading();
setTimeOut( () => {
  Linking.openURL(event.url)
}, 1000);

Это сработало хорошо.

Ответ 10

Решение для тех, кто использует выставку:

import * as WebBrowser from 'expo-web-browser';
import { WebView } from 'react-native-webview';

...

render() {

    return (
        <WebView

            source={{
                uri: uri
            }}

            ref={ (ref) => { this.webview = ref; } }

            onNavigationStateChange={ (event) => {
                if (event.url !== uri) {
                    this.webView.stopLoading();
                    WebBrowser.openBrowserAsync(event.url);
                }
            }}
        />
    );
}

WebBrowser устанавливается через: expo install expo-web-browser