简体   繁体   English

在 React Native 的 Webview 中,injectedJavaScript 不起作用

[英]injectedJavaScript is not working in Webview of react native

I am not able to inject this simple js code into react-native webview.我无法将这个简单的 js 代码注入到 react-native webview 中。

I referred this link also but no solution provided here.我也提到了这个链接,但这里没有提供解决方案。

Then I found this one which works for html props but not uri. 然后我发现这个适用于 html props 但不适用于 uri。

import React, { Component } from 'react';
import { Platform,
  StyleSheet,
  Text,
  View,
  WebView
} from 'react-native';

export default class App extends Component<{}> {

  injectjs(){

    let jsCode = 'alert(hello)';
    return jsCode;
  }

  render() {
    return <WebView 
    javaScriptEnabled={true}
    injectedJavaScript={this.injectjs()} 
    source={{uri:"https://www.google.com"}} style={{ marginTop: 20 }} />;
  }
}

Well, you have more than one issue here.好吧,你在这里有不止一个问题。 First one is your web view needs to be wrapped in a containing View component with flex: 1. Second, injectedJavascript only accepts a string - not a function.第一个是您的 web 视图需要包含在一个包含 flex 的 View 组件中: 1. 其次,injectedJavascript 只接受一个字符串 - 而不是一个函数。 Third, it seems you are attempting to use hello as a variable without defining it, or if it is a string than your syntax needs to be something like this: injectedJavascript={'alert("hello")'}.第三,您似乎试图将 hello 作为变量使用而不定义它,或者如果它是一个字符串,那么您的语法需要是这样的:injectedJavascript={'alert("hello")'}。 Furthermore, injectedJavascript is already fired when the view loads so you are all good there if that's what you are intending to do.此外,当视图加载时,injectedJavascript 已经被触发,所以如果这是你打算做的,那么你在那里都很好。 You can inject javascript when the web view starts loading though, using a combination of the props, onLoadStart and injectJavascript, but the implementation is quite different, so that's a different question.您可以在 web 视图开始加载时注入 javascript,使用 props、onLoadStart 和 injectJavascript 的组合,但实现完全不同,所以这是一个不同的问题。 Try this code:试试这个代码:

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View,
  WebView
} from 'react-native';

export default class App extends Component {

  render() {
    let yourAlert = 'alert("hello")'
    return (
     <View style={{flex: 1}}>
       <WebView
        javaScriptEnabled={true}
        domStorageEnabled={true}
        injectedJavaScript={yourAlert}
        source={{ uri: "https://www.google.com" }} style={{ marginTop: 20  }} />
    </View>
   )
  }
}

Add onMessage method does work.添加onMessage方法确实有效。

import React, { Component } from 'react';
import { Platform,
  StyleSheet,
  Text,
  View,
  WebView
} from 'react-native';

export default class App extends Component<{}> {
  render() {
    return 
      <WebView 
        javaScriptEnabled={true}
        injectedJavaScript={'alert("hello")'} 
        source={{uri:"https://www.google.com"}} style={{ marginTop: 20 }}
        onMessage={(event) => {
          console.log('event: ', event)
        }}
      />;
  }
}

You need to add onMessage props.您需要添加 onMessage 道具。

在此处输入图片说明

I ran into this issue as well, and I was able to get it to work by setting mixedContentMode:我也遇到了这个问题,我可以通过设置 mixContentMode 让它工作:

mixedContentMode={'compatibility'} mixContentMode={'兼容性'}

see below where props.url = {uri:' https://google.com '} quick test javascript pastes "look at me, I'm injecting" into the search box.见下文,其中 props.url = {uri:' https://google.com '} 快速测试 javascript 将“看着我,我正在注射”粘贴到搜索框中。

import React from 'react';
import { Button, StyleSheet, Text, View, ScrollView, WebView } from 'react-native';

export class WebViewController extends React.Component {

    constructor(props) {
        super(props);
    }

    render() {
        const url = this.props.url;
        console.log(`v:1`);
        console.log(`url info: ${JSON.stringify(url)}`);
        console.log(`javascript: ${Constants.javascript.injection}`);
        return (
            <View style={styles.root}>
                <WebView
                    source={url}
                    injectedJavaScript={Constants.javascript.injection}
                    mixedContentMode={'compatibility'}
                    javaScriptEnabled={true}
                    style={styles.webview}
                />
            </View>
        );
    }
}

const styles = StyleSheet.create({
    root: {
        flex:1,
        alignSelf: 'stretch',
    },
    webview: {
        flex:1,
        alignSelf: 'stretch',
    },
})

const Constants = {
    javascript: {
        injection: `
            Array.from(document.getElementsByTagName('input')).forEach((item) => {
                if(item.type == "search") {
                    item.value = "look at me, I'm injecting";
                }
            })
        `
    }
}

I expect the problem is when your adding your html directly and injecting javascript the webview considers the injection as javascript from the same origin.我预计问题是当您直接添加 html 并注入 javascript 时,webview 会将注入视为来自同一来源的 javascript。 Unlike when you load a page through a url, where your javascript is foreign and is considered outside of the origin by the default value of mixedContentMode which is 'never'与通过 url 加载页面不同,当您通过 url 加载页面时,您的 javascript 是外部的,并且被 mixContentMode 的默认值视为“从不”

see: https://facebook.github.io/react-native/docs/webview.html#mixedcontentmode见: https : //facebook.github.io/react-native/docs/webview.html#mixedcontentmode

mixedContentMode Specifies the mixed content mode. mixContentMode 指定混合内容模式。 ie WebView will allow a secure origin to load content from any other origin.即 WebView 将允许安全来源从任何其他来源加载内容。

Possible values for mixedContentMode are: mixContentMode 的可能值是:

'never' (default) - WebView will not allow a secure origin to load content from an insecure origin. “从不”(默认)- WebView 不允许安全来源从不安全来源加载内容。 'always' - WebView will allow a secure origin to load content from any other origin, even if that origin is insecure. 'always' - WebView 将允许安全来源从任何其他来源加载内容,即使该来源不安全。 'compatibility' - WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content. “兼容性” - WebView 将尝试与现代 Web 浏览器在混合内容方面的方法兼容。

https://github.com/react-native-webview/react-native-webview/blob/master/docs/Guide.md#the-injectjavascript-method https://github.com/react-native-webview/react-native-webview/blob/master/docs/Guide.md#the-injectjavascript-method

follow this link 

The injectJavaScript method

While convenient, the downside to the previously mentioned 
injectedJavaScript prop is that it only runs once. That's why we 
also expose a method on the webview ref called injectJavaScript 
(note the slightly different name!).

The problem is because the Javascript code needs to be executed after the WebView load completely. 问题是因为在完全加载WebView之后需要执行Javascript代码。

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View,
  WebView
} from 'react-native';

export default class App extends Component {

  injectjs() {

    let message = "Hello";

    let jsCode = `
      setTimeout(() => {
        alert('${message}');
      }, 1500)`;

    return jsCode;
  }

  render() {
    return <WebView
      javaScriptEnabled={true}
      injectedJavaScript={this.injectjs()}
      source={{ uri: "https://www.google.com" }} style={{ marginTop: 20 }} />;
  }
}

You can use setTimeout for load your Javascript code some seconds after the WebView loads completely. WebView完全加载后几秒钟,您可以使用setTimeout加载Javascript代码。

Also, I recommend you to use `` instead of '' with it you can put other variables inside your variable. 另外,我建议你使用``而不是'' ,你可以在变量中加入其他变量。

Example

injectjs(){

    var message = "Hello";

    let jsCode = `alert('${message}')`;
    return jsCode;
}

Adding a empty ref & onMessage fixed this for me:添加一个空的 ref & onMessage 为我解决了这个问题:

onMessage={(event) => {}}
ref={() => {}}

For anyone struggling with this in 2021, what I ended up having to do (pretty dirty solution but it worked), was to poll for the necessary dependencies I was injecting into the window object via injectedJavaScriptBeforeContentLoaded , and only running the rest of my code when they became available.对于在 2021 年为此苦苦挣扎的任何人,我最终不得不做的事情(相当肮脏的解决方案,但它奏效了),是轮询我通过injectedJavaScriptBeforeContentLoaded注入到window对象中的必要依赖项,并且仅在以下情况下运行我的其余代码他们变得可用。

My solution ended up looking something like this:我的解决方案最终看起来像这样:

function app () {
    // Continue to re-call self until frame data is available
    if (typeof window._rendererFrameData === 'undefined') {
        setTimeout(app, 250);
        return;
    }

    // Passed in from RN
    var size = window._rendererSize;
    var pixelSize = window._rendererPixelSize;

    // Picture data
    var frames = [];
    window._rendererFrameData.forEach(function(frameString) {
        frames.push(frameString.split(''));
    });
    var frameIndex = 0;

    var canvas = document.querySelector('canvas');
    canvas.setAttribute('width', size * pixelSize + 2);
    canvas.setAttribute('height', size * pixelSize + 2);
    document.body.setAttribute('width', size * pixelSize + 2);
    document.body.setAttribute('height', size * pixelSize + 2);
    

    var ctx = canvas.getContext('2d');
    
    // ... rest of renderer logic
}

app();

Note the if statement w/ setTimeout and return at the start.请注意带有setTimeout的 if 语句并在开始时返回。 Basically it checks if my injected data is undefined, then queues the function to re-run in 250 milliseconds and bails out.基本上它会检查我注入的数据是否未定义,然后将函数排队以在 250 毫秒内重新运行并退出。 This continues until the data is available.这一直持续到数据可用为止。

Feels like a seriously bad case of band-aid solution, but it works for my app!感觉像是创可贴解决方案的一个非常糟糕的案例,但它适用于我的应用程序!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM