react-native-webview 如何注入 javascript?
Posted
技术标签:
【中文标题】react-native-webview 如何注入 javascript?【英文标题】:react-native-webview how to inject javascript? 【发布时间】:2020-10-05 04:55:31 【问题描述】:在 android 上,我一直在使用 expo-stripe-checkout 在 Expo 托管应用上进行付款。在我更新到最新版本的 expo 和 react-native 之前,一切都运行良好。现在,没有一个回调,如 onClose 和 onPaymentSuccess 正在工作。似乎 WebView 已从 react-native 中删除,所以我直接从 react-native-webview
导入。
我没有使用expo-stripe-checkout
,而是创建了自己的组件,以尝试解决正在发生的事情,似乎WebView 的injectedjavascript
根本没有运行,因此window.postMessage
或window.ReactNativeWebView.postMessage
没有运行不工作。
package.json:
"name": "example",
"version": "0.0.6",
"private": true,
"devDependencies":
"jest-expo": "^37.0.0",
"react-test-renderer": "16.0.0",
"schedule": "^0.4.0"
,
"main": "./node_modules/expo/AppEntry.js",
"scripts":
"start": "expo start",
"eject": "expo eject",
"android": "expo start --android",
"ios": "expo start --ios",
"test": "node node_modules/jest/bin/jest.js --watch",
"prettier": "./node_modules/prettier/bin-prettier.js --single-quote --trailing-comma es5 --print-width 100 --write 'app/**/*.js' -l"
,
"jest":
"preset": "jest-expo"
,
"dependencies":
"@ptomasroos/react-native-multi-slider": "^1.0.0",
"@react-native-community/masked-view": "^0.1.10",
"@react-navigation/drawer": "^5.6.4",
"@react-navigation/native": "^5.2.3",
"@react-navigation/stack": "^5.2.18",
"axios": "^0.17.1",
"babel-plugin-transform-remove-console": "^6.9.4",
"emoji-utils": "^1.0.1",
"expo": "^37.0.0",
"expo-analytics": "^1.0.9",
"expo-apple-authentication": "^2.1.1",
"expo-av": "~8.1.0",
"expo-blur": "~8.1.0",
"expo-branch": "~2.1.0",
"expo-constants": "~9.0.0",
"expo-facebook": "~8.1.0",
"expo-font": "~8.1.0",
"expo-image-manipulator": "~8.1.0",
"expo-image-picker": "~8.1.0",
"expo-linear-gradient": "~8.1.0",
"expo-permissions": "~8.1.0",
"expo-stripe-checkout": "^1.0.1",
"immutability-helper": "^2.8.1",
"lottie-react-native": "~2.6.1",
"moment": "^2.22.1",
"prettier": "^1.12.1",
"react": "16.9.0",
"react-native": "0.61.4",
"react-native-animate-number": "^0.1.2",
"react-native-aws3": "0.0.9",
"react-native-branch": "4.2.1",
"react-native-calendars": "^1.20.0",
"react-native-circular-action-menu": "^0.5.0",
"react-native-circular-progress": "^1.0.1",
"react-native-datepicker": "^1.7.2",
"react-native-gesture-handler": "^1.6.1",
"react-native-gifted-chat": "0.13.0",
"react-native-google-places-autocomplete": "^1.4.0",
"react-native-invertible-scroll-view": "^1.1.1",
"react-native-keyboard-aware-scroll-view": "0.9.1",
"react-native-maps": "0.26.1",
"react-native-modal": "^11.5.3",
"react-native-modal-dropdown": "^0.6.2",
"react-native-reanimated": "^1.8.0",
"react-native-safe-area-context": "^0.7.3",
"react-native-screens": "^2.7.0",
"react-native-scroll-into-view": "^0.1.4",
"react-native-snap-carousel": "^3.7.2",
"react-native-status-bar-height": "^3.0.0-alpha.1",
"react-native-svg": "11.0.1",
"react-native-svg-icon": "^0.8.1",
"react-native-swipe-gestures": "^1.0.5",
"react-native-unimodules": "~0.8.1",
"react-native-webview": "^10.3.1",
"react-redux": "^5.0.7",
"react-timer-mixin": "^0.13.4",
"react-visibility-sensor": "^4.1.0",
"redux": "^4.0.0",
"redux-thunk": "^2.3.0",
"sentry-expo": "~2.0.0",
"socket.io-client": "^2.0.4"
我尝试了网络上的几种不同建议,但没有任何效果:
StripeCheckout.js
import React, Component from 'react';
import Platform, View, ViewPropTypes from 'react-native';
import PropTypes from 'prop-types';
import WebView from 'react-native-webview'
class StripeCheckout extends Component
render()
const
publicKey,
amount,
allowRememberMe,
currency,
description,
imageUrl,
storeName,
prepopulatedEmail,
style,
onPaymentSuccess,
onClose
= this.props;
const jsCode = `(function()
console.log('hello')
var originalPostMessage = window.ReactNativeWebView.postMessage;
var patchedPostMessage = function(message, targetOrigin, transfer)
originalPostMessage(message, targetOrigin, transfer);
;
patchedPostMessage.toString = function()
return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
;
window.ReactNativeWebView.postMessage = patchedPostMessage;
)();`;
const runFirst = `
console.log('firstRun')
window.isNativeApp = true;
true; // note: this is required, or you'll sometimes get silent failures
`;
return (
<WebView
ref=(ref) => this.webview = ref;
javaScriptEnabled=true
injectedJavaScriptForMainFrameOnly=false
scrollEnabled=false
bounces=false
messagingEnabled=true
onMessage=(event) => console.log(event)
onPaymentSuccess(event.nativeEvent.data)
injectedJavaScriptBeforeContentLoaded=runFirst
injectedJavaScript=jsCode
source= html: `<script src="https://checkout.stripe.com/checkout.js"></script>
<script>
var handler = StripeCheckout.configure(
key: '$publicKey',
image: '$imageUrl',
locale: 'auto',
token: function(token)
window.ReactNativeWebView.postMessage(token.id, token.id);
,
);
window.onload = function()
console.log('onload')
handler.open(
image: '$imageUrl',
name: '$storeName',
description: '$description',
amount: $amount,
currency: '$currency',
allowRememberMe: $allowRememberMe,
email: '$prepopulatedEmail',
closed: function()
window.ReactNativeWebView.postMessage("WINDOW_CLOSED", "*");
);
;
</script>`
style=[ flex: 1 , style]
scalesPageToFit=Platform.OS === 'android'
/>
);
StripeCheckout.propTypes =
publicKey: PropTypes.string.isRequired,
amount: PropTypes.number.isRequired,
imageUrl: PropTypes.string.isRequired,
storeName: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
allowRememberMe: PropTypes.bool.isRequired,
onPaymentSuccess: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
currency: PropTypes.string,
prepopulatedEmail: PropTypes.string,
style: ViewPropTypes.object
;
StripeCheckout.defaultProps =
prepopulatedEmail: '',
currency: 'USD',
;
export default StripeCheckout;
没有控制台记录。条带集成弹出并成功返回一个令牌,但没有任何反应,并且组件没有接收到令牌(我可以看到它正在从条带日志中返回一个令牌)。
如果还有什么我应该发布的,请告诉我。谢谢!
【问题讨论】:
【参考方案1】:我脑子里想的几件事:
-
在你的 package.json 中,react-native 版本应该是
"react-native": "https://github.com/expo/react-native/archive/sdk-37.0.1.tar.gz",
(Expo SDK 37 已经基于 0.61.4,但带有 Expo 特定的 mods)。在以前的版本中让 expo-stripe-checkout 像以前一样工作可能就这么简单。 The SDK 37 announcement blog post 提供有关 SDK 升级过程的更多信息,即:
在你的项目目录下运行如果这无助于让expo upgrade
(需要最新版本的expo-cli,你可以用npm i -g expo-cli
更新)。 请务必查看更改日志以了解其他重大更改! ...
expo-checkout-stripe
再次工作(无论如何都要修复您的 React Native 版本,如果您不这样做,您肯定会遇到更多的 Expo 问题),请尝试以下一项或两项操作网页浏览:
使用injectJavaScript
按照(指南> JS 和Native 之间的通信> injectJavaScript 方法)[https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#the-injectjavascript-method"]。在你的情况下,这就像
this.webview.injectJavaScript(jsCode)
Spitballing 甚至比之前的建议更多,但可以尝试将 webview 的脚本标签包装在 html/head/body 标签中。尽职调查/消除变量比其他任何事情都多。
我希望这些建议之一至少能让你走上正确的道路。
【讨论】:
以上是关于react-native-webview 如何注入 javascript?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 React-Native Webview 的注入 JavaScript 道具中使用 RegExp?
如何在 iOS 的 WebView(react-native-webview) 中设置自定义字体?
如何在 react-native-webview 中启用安全上下文?
如何在 appState 更改时重新加载 react-native-webview 内容