response-native-webview Вызов определенной функции c javascript из html - PullRequest
2 голосов
/ 17 января 2020

Ниже приведен веб-вид, я использую встроенный HTML для того же.

<WebView
        javaScriptEnabled={true}
        domStorageEnabled={true}
        allowFileAccess={true}
        originWhitelist={['*']}
        style={{height: deviceHeight, width: deviceWidth, margin: 10}}
        // source={{ uri: 'https://www.google.com/'}}
        source={{
          html:
            '<script> function invokeHello() { window.ReactNativeWebView.postMessage("Hello") } function fillQRCode() { window.alert("filling qrcode"); document.getElementById("qr_code").value = "QR Code"; } function scanQRCode() { let data = {"nativeItemToAccess": "camera", "operation": { "type": "CALLBACK", "fieldId": "qr_code", "callback": `${fillQRCode}` }}; window.ReactNativeWebView.postMessage(JSON.stringify(data)); }</script> <!-- <form method="get" enctype="application/x-www-form-urlencoded" action="/html/codes/html_form_handler.cfm" onSubmit="invokeHello()"> --> <p><label>Name<input type="text" name="customer_name" required></label> </p> <p><label>Phone <input type="tel" name="phone_number" id="phone_number"></label></p> <p><label>QR Code <input type="text" disabled name="qr_code" id="qr_code"></label><p></p><button onclick="scanQRCode()">Scan</button></p></p> <p><button>Submit Booking</button></p><!-- </form> -->',
        }}
        // injectedJavaScript={runFirst}
        ref={r => (this.webref = r)}
        onMessage={event => {
          if (this.webref) {
            let data = JSON.parse(event.nativeEvent.data);
            console.log('1: data being received: ', data);
            if(data) {
              switch(data.nativeItemToAccess) {
                case 'camera':
                  this.performOperation(data);
                  break;
                case 'test':
                  alert('test is invoked');
                  break;
              }
            }
          }
        }}
      />

Найдите ниже тот же html, который встроен (публикуется только для того, чтобы сделать его более читабельным),

<script> 
  function invokeHello() { window.ReactNativeWebView.postMessage("Hello") }
  function fillQRCode() { window.alert("filling qrcode"); document.getElementById("qr_code").value = "QR Code"; }
  function scanQRCode() {

    let data = {"nativeItemToAccess": "camera", "operation": {
      "type": "CALLBACK",
      "fieldId": "qr_code",
      "callback": `${fillQRCode}`
    }};
    window.ReactNativeWebView.postMessage(JSON.stringify(data));
  }
</script> 
<!-- <form method="get" enctype="application/x-www-form-urlencoded" action="/html/codes/html_form_handler.cfm" onSubmit="invokeHello()"> -->
   <p><label>Name<input type="text" name="customer_name" required></label> </p>
   <p><label>Phone <input type="tel" name="phone_number" id="phone_number"></label></p>
   <p><label>QR Code <input type="text" disabled name="qr_code" id="qr_code"></label><p></p><button onclick="scanQRCode()">Scan</button></p></p>
   <p><button>Submit Booking</button></p>
<!-- </form> -->

Когда я нажимаю на кнопку сканирования, onMessage вызывается, и данные, которые передаются, принимаются правильно. Я буду вызывать разные функции в зависимости от полученных данных.

Ниже приведены функции, которые вызываются для камеры,

performOperation = data => {
    switch (data.operation.type) {
      case 'FIELD_UPDATE':
        this.updateField(data.operation.fieldId);
        break;
      case 'CALLBACK':
        this.performCallback(data.operation.callback);
        break;
    }
  };

  performCallback = callback => {
    console.log('2: callback: ', callback);
    this.webref.injectJavaScript(`
    try {
      var fn = window[${callback}];
      if (typeof fn === "function") {
        fn();
      } else {
        window.alert('this is not a function '+ typeof fn);
      }
      true;
    } catch (e) {
      window.alert('unable to call the function: '+ e);
    }
  `);
  };

  updateField = fieldId => {
    this.webref.injectJavaScript(`
    document.getElementById("${fieldId}").value = "QR Code";
    `);
  };

performOperation функция обрабатывает вызов метода javascript или он просто заполнит текстовое поле, в зависимости от data.operation.type. Итак, теперь data.operation.type - это CALLBACK, поэтому вызывается performCallback, но я не могу вызвать функцию, полученную в качестве входных данных в объекте. Объект выглядит следующим образом:

{"nativeItemToAccess": "camera", "operation": {
"type": "CALLBACK",
"fieldId": "qr_code",
"callback": ${fillQRCode}
}};

fillQRCode - это функция, присутствующая в теге <script> html.

Как преобразовать полученную функцию, которая является в форме строки при получении, чтобы функционировать и вызывать то же самое.

1 Ответ

0 голосов
/ 17 января 2020

Я изменил способ передачи функции следующим образом:

{"nativeItemToAccess": "camera", "operation": {
      "type": "CALLBACK",
      "fieldId": "qr_code",
      "callback": "fillQRCode"
    }};

, то есть вместо передачи всей функции (что я чувствую сейчас неправильно), я передал только имя функции и вызвал функцию следующим образом:

performCallback = callback => {
    console.log('2: callback: ', callback);
    var qrCode = 'zdjkcnsjkdnsdkfjnjk';
    this.webref.injectJavaScript(`
    try {
      ${callback}("${qrCode}")
      true;
    } catch (e) {
      window.alert('unable to call the function: '+ e);
    }
  `);
  };
...