【问题标题】:injectedJavaScript is not working in Webview of react native在 react native 的 Webview 中注入的 JavaScript 不起作用
【发布时间】:2018-03-23 05:58:59
【问题描述】:

我无法将这个简单的 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.

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 }} />;
  }
}

【问题讨论】:

    标签: javascript android react-native webview


    【解决方案1】:

    嗯,你有不止一个问题。第一个是您的 Web 视图需要用 flex 包装在包含 View 组件中: 1。其次,injectJavascript 只接受一个字符串 - 而不是一个函数。第三,您似乎正在尝试使用 hello 作为变量而不定义它,或者如果它是一个字符串,而不是您的语法需要是这样的:injectedJavascript={'alert("hello")'}。此外,在视图加载时,injectJavascript 已经被触发,因此如果您打算这样做,那么您在那里一切都很好。您可以在 web 视图开始加载时注入 javascript,使用 props、onLoadStart 和 injectJavascript 的组合,但实现完全不同,所以这是一个不同的问题。试试这个代码:

    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>
       )
      }
    }
    

    【讨论】:

    • 是否可以添加一个等待令牌并作为字符串返回到注入的JavaScript 的异步函数?我似乎无法弄清楚。感谢您的帮助
    【解决方案2】:

    添加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)
            }}
          />;
      }
    }
    

    【讨论】:

    • 用虚拟函数添加空的onMessage 就像一个魅力。
    • 很好,也为我工作!另外,值得注意的是,我将它传递为injectedJavascript 而不是injectedJavaScript 并带有大写S,所以要小心这个愚蠢的错误!
    【解决方案3】:

    你需要添加 onMessage 属性。

    【讨论】:

      【解决方案4】:

      我也遇到了这个问题,我可以通过设置混合内容模式来让它工作:

      mixedContentMode={'compatibility'}

      请参阅下面的 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";
                      }
                  })
              `
          }
      }
      

      我预计问题是当您直接添加 html 并注入 javascript 时,webview 会将注入视为来自同一来源的 javascript。与通过 url 加载页面时不同,在这种情况下,您的 javascript 是外来的,并且默认值是 'never' 的混合内容模式被认为是在原点之外的

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

      混合内容模式 指定混合内容模式。即 WebView 将允许安全源从任何其他源加载内容。

      mixedContentMode 的可能值为:

      'never'(默认)- WebView 将不允许安全源从不安全的源加载内容。 'always' - WebView 将允许安全源从任何其他源加载内容,即使该源不安全。 'compatibility' - WebView 将尝试与现代 Web 浏览器在混合内容方面的方法兼容。

      【讨论】:

        【解决方案5】:

        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!).
        

        【讨论】:

          【解决方案6】:

          添加一个空的 ref 和 onMessage 为我解决了这个问题:

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

          【讨论】:

            【解决方案7】:

            对于任何在 2021 年为此苦苦挣扎的人,我最终不得不做的事情(相当肮脏的解决方案,但它有效),就是轮询我通过 injectedJavaScriptBeforeContentLoaded 注入到 window 对象中的必要依赖项,并且只当它们可用时运行我的其余代码。

            我的解决方案最终看起来像这样:

            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();
            

            注意带有setTimeout 的 if 语句并在开头返回。基本上,它会检查我注入的数据是否未定义,然后将函数排入队列以在 250 毫秒内重新运行并退出。这种情况一直持续到数据可用为止。

            感觉像是一个非常糟糕的创可贴解决方案,但它适用于我的应用!

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-10-05
              • 1970-01-01
              • 1970-01-01
              • 2017-04-30
              • 1970-01-01
              相关资源
              最近更新 更多