From 6c8f977600994a1490f8f66120057151d4711acd Mon Sep 17 00:00:00 2001 From: wangcuijuan Date: Tue, 24 Dec 2024 15:25:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9webview=E9=80=9A=E4=BF=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/mpx-webview/H5/webviewbridge.min.js | 2 +- .../runtime/components/react/mpx-web-view.tsx | 14 +++- .../dist/webviewbridge.esm.browser.js | 78 ++++++++++++------- .../dist/webviewbridge.esm.browser.min.js | 2 +- .../webview-bridge/dist/webviewbridge.esm.js | 71 ++++++++++------- packages/webview-bridge/dist/webviewbridge.js | 71 ++++++++++------- .../webview-bridge/dist/webviewbridge.min.js | 2 +- packages/webview-bridge/src/index.js | 78 ++++++++++++------- 8 files changed, 203 insertions(+), 115 deletions(-) diff --git a/examples/mpx-webview/H5/webviewbridge.min.js b/examples/mpx-webview/H5/webviewbridge.min.js index 7ac85a8e7..a8a6c7b98 100644 --- a/examples/mpx-webview/H5/webviewbridge.min.js +++ b/examples/mpx-webview/H5/webviewbridge.min.js @@ -3,4 +3,4 @@ * (c) 2024 @mpxjs team * @license Apache */ -var e,o;e=this,o=function(){"use strict";var e,o,a,t,n=Object.assign({wx:{url:"https://res.wx.qq.com/open/js/jweixin-1.3.2.js"},qq:{url:"https://qqq.gtimg.cn/miniprogram/webview_jssdk/qqjssdk-1.0.0.js"},my:{url:"https://appx/web-view.min.js"},swan:{url:"https://b.bdstatic.com/searchbox/icms/searchbox/js/swan-2.0.4.js"},tt:{url:"https://lf3-cdn-tos.bytegoofy.com/obj/goofy/developer/jssdk/jssdk-1.2.1.js"}},window.sdkUrlMap),i=null,r=0,c=(a=location.href,(t=/mpx_webview_id=(\d+)/g.exec(a))&&t[1]&&(o=+t[1]),o),s={},d=navigator.userAgent;d.indexOf("AlipayClient")>-1&&d.indexOf("MiniProgram")>-1?i="my":d.toLowerCase().indexOf("miniprogram")>-1?i=d.indexOf("QQ")>-1?"qq":"wx":d.indexOf("swan/")>-1?i="swan":d.indexOf("toutiao")>-1?i="tt":(i="web",window.addEventListener("message",(function(e){var o=e.data,a=o;try{"string"==typeof o&&(a=JSON.parse(o))}catch(e){}var t=a,n=t.callbackId,i=t.error,r=t.result;void 0!==n&&s[n]&&(i?s[n](i):s[n](null,r),delete s[n])}),!1));var g=!1;function w(o){g?o():e.then((function(){g=!0,o()}))}var p={config:function(e){"wx"===i?w((function(){window.wx&&window.wx.config(e)})):console.warn("\u975e\u5fae\u4fe1\u73af\u5883\u4e0d\u9700\u8981\u914d\u7f6econfig")}};function l(e){for(var o=arguments.length,a=new Array(o>1?o-1:0),t=1;t1&&void 0!==arguments[1]?arguments[1]:{},a=o.time,t=void 0===a?5e3:a,n=o.crossOrigin,i=void 0!==n&&n;function r(){return new Promise((function(o,a){var t=document.createElement("script");t.type="text/javascript",t.async="async",i&&(t.crossOrigin="anonymous"),t.onload=t.onreadystatechange=function(){this.readyState&&!/^(loaded|complete)$/.test(this.readyState)||(o(),t.onload=t.onreadystatechange=null)},t.onerror=function(){a(new Error("load ".concat(e," error"))),t.onerror=null},t.src=e,document.getElementsByTagName("head")[0].appendChild(t)}))}function c(){return new Promise((function(o,a){setTimeout((function(){a(new Error("load ".concat(e," timeout")))}),t)}))}return Promise.race([r(),c()])}(n[i].url):Promise.reject(new Error("\u672a\u627e\u5230\u5bf9\u5e94\u7684sdk")):Promise.resolve(),m(),p},"object"==typeof exports&&"undefined"!=typeof module?module.exports=o():"function"==typeof define&&define.amd?define(o):(e=e||self).mpx=o(); \ No newline at end of file +var e,a;e=this,a=function(){"use strict";var e,a,o,t,n=Object.assign({wx:{url:"https://res.wx.qq.com/open/js/jweixin-1.3.2.js"},qq:{url:"https://qqq.gtimg.cn/miniprogram/webview_jssdk/qqjssdk-1.0.0.js"},my:{url:"https://appx/web-view.min.js"},swan:{url:"https://b.bdstatic.com/searchbox/icms/searchbox/js/swan-2.0.4.js"},tt:{url:"https://lf3-cdn-tos.bytegoofy.com/obj/goofy/developer/jssdk/jssdk-1.2.1.js"}},window.sdkUrlMap),i=null,r=0,c=(o=location.href,(t=/mpx_webview_id=(\d+)/g.exec(o))&&t[1]&&(a=+t[1]),a),s={},d=function(e){var a=e.callbackId,o=e.error,t=e.result;void 0!==a&&s[a]&&(o?s[a](o):s[a](null,t),delete s[a])},w=navigator.userAgent;w.indexOf("AlipayClient")>-1&&w.indexOf("MiniProgram")>-1?i="my":w.toLowerCase().indexOf("miniprogram")>-1?i=w.indexOf("QQ")>-1?"qq":"wx":w.indexOf("swan/")>-1?i="swan":w.indexOf("toutiao")>-1&&(i="tt"),window.ReactNativeWebView?(i="rn",window.mpxWebviewMessageCallback=d):(i="web",window.addEventListener("message",(function(e){var a=e.data,o=a;try{"string"==typeof a&&(o=JSON.parse(a))}catch(e){}d(o)}),!1));var g=!1;function p(a){g?a():e.then((function(){g=!0,a()}))}var l={config:function(e){"wx"===i?p((function(){window.wx&&window.wx.config(e)})):console.warn("\u975e\u5fae\u4fe1\u73af\u5883\u4e0d\u9700\u8981\u914d\u7f6econfig")}};function v(e){for(var a=arguments.length,o=new Array(a>1?a-1:0),t=1;t1&&void 0!==arguments[1]?arguments[1]:{},o=a.time,t=void 0===o?5e3:o,n=a.crossOrigin,i=void 0!==n&&n;function r(){return new Promise((function(a,o){var t=document.createElement("script");t.type="text/javascript",t.async="async",i&&(t.crossOrigin="anonymous"),t.onload=t.onreadystatechange=function(){this.readyState&&!/^(loaded|complete)$/.test(this.readyState)||(a(),t.onload=t.onreadystatechange=null)},t.onerror=function(){o(new Error("load ".concat(e," error"))),t.onerror=null},t.src=e,document.getElementsByTagName("head")[0].appendChild(t)}))}function c(){return new Promise((function(a,o){setTimeout((function(){o(new Error("load ".concat(e," timeout")))}),t)}))}return Promise.race([r(),c()])}(n[i].url):Promise.reject(new Error("\u672a\u627e\u5230\u5bf9\u5e94\u7684sdk")):Promise.resolve(),m(),l},"object"==typeof exports&&"undefined"!=typeof module?module.exports=a():"function"==typeof define&&define.amd?define(a):(e=e||self).mpx=a(); \ No newline at end of file diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-web-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-web-view.tsx index fd6a89340..787c94a3d 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-web-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-web-view.tsx @@ -111,6 +111,12 @@ const _WebView = forwardRef, WebViewProps>((pr } true; ` + const sendMessage = function(params: string) { + return ` + window.mpxWebviewMessageCallback(${params}) + true; + ` + } const _changeUrl = function (navState: WebViewNavigation) { if (navState.navigationType) { // navigationType这个事件在页面开始加载时和页面加载完成时都会被触发所以判断这个避免其他无效触发执行该逻辑 currentPage.__webViewUrl = navState.url @@ -182,21 +188,21 @@ const _WebView = forwardRef, WebViewProps>((pr asyncCallback && asyncCallback.then((res: any) => { if (webViewRef.current?.postMessage) { - const test = JSON.stringify({ + const result = JSON.stringify({ type, callbackId: data.callbackId, result: res }) - webViewRef.current.postMessage(test) + webViewRef.current.injectJavaScript(sendMessage(result)) } }).catch((error: any) => { if (webViewRef.current?.postMessage) { - const test = JSON.stringify({ + const result = JSON.stringify({ type, callbackId: data.callbackId, error }) - webViewRef.current.postMessage(test) + webViewRef.current.injectJavaScript(sendMessage(result)) } }) } diff --git a/packages/webview-bridge/dist/webviewbridge.esm.browser.js b/packages/webview-bridge/dist/webviewbridge.esm.browser.js index e8b97d2f1..409c17b1b 100644 --- a/packages/webview-bridge/dist/webviewbridge.esm.browser.js +++ b/packages/webview-bridge/dist/webviewbridge.esm.browser.js @@ -75,6 +75,32 @@ let env = null; let callbackId = 0; const clientUid = getMpxWebViewId(); const callbacks = {}; + +const runCallback = (msgData) => { + const { callbackId, error, result } = msgData; + if (callbackId !== undefined && callbacks[callbackId]) { + if (error) { + callbacks[callbackId](error); + } else { + callbacks[callbackId](null, result); + } + delete callbacks[callbackId]; + } +}; + +const eventListener = (event) => { + // 接收web-view的回调 + const data = event.data; + let msgData = data; + try { + if (typeof data === 'string') { + msgData = JSON.parse(data); + } + } catch (e) { + } + runCallback(msgData); +}; + // 环境判断逻辑 const systemUA = navigator.userAgent; if (systemUA.indexOf('AlipayClient') > -1 && systemUA.indexOf('MiniProgram') > -1) { @@ -85,32 +111,16 @@ if (systemUA.indexOf('AlipayClient') > -1 && systemUA.indexOf('MiniProgram') > - env = 'swan'; } else if (systemUA.indexOf('toutiao') > -1) { env = 'tt'; +} if (window.ReactNativeWebView) { + env = 'rn'; + window.mpxWebviewMessageCallback = runCallback; } else { env = 'web'; - window.addEventListener('message', (event) => { - // 接收web-view的回调 - const data = event.data; - let msgData = data; - try { - if (typeof data === 'string') { - msgData = JSON.parse(data); - } - } catch (e) { - } - const { callbackId, error, result } = msgData; - if (callbackId !== undefined && callbacks[callbackId]) { - if (error) { - callbacks[callbackId](error); - } else { - callbacks[callbackId](null, result); - } - delete callbacks[callbackId]; - } - }, false); + window.addEventListener('message', eventListener, false); } const initWebviewBridge = () => { - sdkReady = env !== 'web' ? SDK_URL_MAP[env].url ? loadScript(SDK_URL_MAP[env].url) : Promise.reject(new Error('未找到对应的sdk')) : Promise.resolve(); + sdkReady = (env !== 'web' && env !== 'rn') ? SDK_URL_MAP[env].url ? loadScript(SDK_URL_MAP[env].url) : Promise.reject(new Error('未找到对应的sdk')) : Promise.resolve(); getWebviewApi(); }; @@ -145,7 +155,7 @@ function postMessage (type, ...extraData) { type = extraData[0]; extraData = extraData.slice(1); } - const data = extraData[0]; + const data = extraData[0] || {}; if (type !== 'getEnv') { const currentCallbackId = ++callbackId; callbacks[currentCallbackId] = (err, res) => { @@ -172,9 +182,15 @@ function postMessage (type, ...extraData) { window.parent.postMessage && window.parent.postMessage(JSON.stringify(postParams), '*'); } } else { - data({ + let result = { webapp: true - }); + }; + if (window.ReactNativeWebView) { + result = { + reactNative: true + }; + } + data(result); } } @@ -307,7 +323,17 @@ const getWebviewApi = () => { 'redirectTo', 'getEnv', 'postMessage', - 'getLoadError', + 'getLocation', + 'invoke' + ], + rn: [ + 'navigateTo', + 'navigateBack', + 'switchTab', + 'reLaunch', + 'redirectTo', + 'getEnv', + 'postMessage', 'getLocation', 'invoke' ], @@ -325,7 +351,7 @@ const getWebviewApi = () => { }); singleApi.forEach((item) => { webviewBridge[item] = (...args) => { - if (env === 'web') { + if (env === 'web' || env === 'rn') { postMessage(item, ...args); } else if (env === 'wx') { runWebviewApiMethod(() => { diff --git a/packages/webview-bridge/dist/webviewbridge.esm.browser.min.js b/packages/webview-bridge/dist/webviewbridge.esm.browser.min.js index efbeb4cfa..be460b7a6 100644 --- a/packages/webview-bridge/dist/webviewbridge.esm.browser.min.js +++ b/packages/webview-bridge/dist/webviewbridge.esm.browser.min.js @@ -3,4 +3,4 @@ * (c) 2024 @mpxjs team * @license Apache */ -let e;const o=Object.assign({wx:{url:"https://res.wx.qq.com/open/js/jweixin-1.3.2.js"},qq:{url:"https://qqq.gtimg.cn/miniprogram/webview_jssdk/qqjssdk-1.0.0.js"},my:{url:"https://appx/web-view.min.js"},swan:{url:"https://b.bdstatic.com/searchbox/icms/searchbox/js/swan-2.0.4.js"},tt:{url:"https://lf3-cdn-tos.bytegoofy.com/obj/goofy/developer/jssdk/jssdk-1.2.1.js"}},window.sdkUrlMap);let a=null,t=0;const n=function(){const e=location.href,o=/mpx_webview_id=(\d+)/g.exec(e);let a;return o&&o[1]&&(a=+o[1]),a}(),i={},s=navigator.userAgent;s.indexOf("AlipayClient")>-1&&s.indexOf("MiniProgram")>-1?a="my":s.toLowerCase().indexOf("miniprogram")>-1?a=s.indexOf("QQ")>-1?"qq":"wx":s.indexOf("swan/")>-1?a="swan":s.indexOf("toutiao")>-1?a="tt":(a="web",window.addEventListener("message",e=>{const o=e.data;let a=o;try{"string"==typeof o&&(a=JSON.parse(o))}catch(e){}const{callbackId:t,error:n,result:s}=a;void 0!==t&&i[t]&&(n?i[t](n):i[t](null,s),delete i[t])},!1));let r=!1;function c(o){r?o():e.then(()=>{r=!0,o()})}const d={config(e){"wx"===a?c(()=>{window.wx&&window.wx.config(e)}):console.warn("\u975e\u5fae\u4fe1\u73af\u5883\u4e0d\u9700\u8981\u914d\u7f6econfig")}};const g=()=>{const e={wx:{keyName:"miniProgram",api:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","postMessage","getEnv"]},tt:{keyName:"miniProgram",api:["redirectTo","navigateTo","switchTab","reLaunch","navigateBack","setSwipeBackModeSync","postMessage","getEnv","checkJsApi","chooseImage","compressImage","previewImage","uploadFile","getNetworkType","openLocation","getLocation"]},swan:{keyName:"webView",api:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","getEnv","postMessage"]},qq:{keyName:"miniProgram",api:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","getEnv","postMessage"]}}[a]||{},o={wx:["checkJSApi","chooseImage","previewImage","uploadImage","downloadImage","getLocalImgData","startRecord","stopRecord","onVoiceRecordEnd","playVoice","pauseVoice","stopVoice","onVoicePlayEnd","uploadVoice","downloadVoice","translateVoice","getNetworkType","openLocation","getLocation","startSearchBeacons","stopSearchBeacons","onSearchBeacons","scanQRCode","chooseCard","addCard","openCard"],my:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","chooseImage","previewImage","getLocation","openLocation","alert","showLoading","hideLoading","getNetworkType","startShare","tradePay","postMessage","onMessage","getEnv"],swan:["makePhoneCall","setClipboardData","getNetworkType","openLocation","getLocation","chooseLocation","chooseImage","previewImage","openShare","navigateToSmartProgram"],web:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","getEnv","postMessage","getLoadError","getLocation","invoke"],tt:[]}[a]||[];(e.api||[]).forEach(o=>{d[o]=(...t)=>{c(()=>{window[a][e.keyName][o](...t)})}}),o.forEach(e=>{d[e]=(...o)=>{"web"===a?function(e,...o){"invoke"===e&&(e=o[0],o=o.slice(1));const a=o[0];if("getEnv"!==e){const s=++t;i[s]=(e,o)=>{e?(a.fail&&a.fail(e),a.complete&&a.complete(e)):(a.success&&a.success(o),a.complete&&a.complete(o)),delete i[s]};const r={type:e,callbackId:t,args:o};void 0!==n&&(r.clientUid=n),window.ReactNativeWebView?window.ReactNativeWebView.postMessage&&window.ReactNativeWebView.postMessage(JSON.stringify(r)):window.parent.postMessage&&window.parent.postMessage(JSON.stringify(r),"*")}else a({webapp:!0})}(e,...o):c("wx"===a?()=>{window[a]&&window[a].ready(()=>{window[a][e](...o)})}:()=>{window[a][e](...o)})}})};e="web"!==a?o[a].url?function(e,{time:o=5e3,crossOrigin:a=!1}={}){return Promise.race([new Promise((o,t)=>{const n=document.createElement("script");n.type="text/javascript",n.async="async",a&&(n.crossOrigin="anonymous"),n.onload=n.onreadystatechange=function(){this.readyState&&!/^(loaded|complete)$/.test(this.readyState)||(o(),n.onload=n.onreadystatechange=null)},n.onerror=function(){t(new Error(`load ${e} error`)),n.onerror=null},n.src=e,document.getElementsByTagName("head")[0].appendChild(n)}),new Promise((a,t)=>{setTimeout(()=>{t(new Error(`load ${e} timeout`))},o)})])}(o[a].url):Promise.reject(new Error("\u672a\u627e\u5230\u5bf9\u5e94\u7684sdk")):Promise.resolve(),g();export default d; \ No newline at end of file +let e;const a=Object.assign({wx:{url:"https://res.wx.qq.com/open/js/jweixin-1.3.2.js"},qq:{url:"https://qqq.gtimg.cn/miniprogram/webview_jssdk/qqjssdk-1.0.0.js"},my:{url:"https://appx/web-view.min.js"},swan:{url:"https://b.bdstatic.com/searchbox/icms/searchbox/js/swan-2.0.4.js"},tt:{url:"https://lf3-cdn-tos.bytegoofy.com/obj/goofy/developer/jssdk/jssdk-1.2.1.js"}},window.sdkUrlMap);let o=null,t=0;const n=function(){const e=location.href,a=/mpx_webview_id=(\d+)/g.exec(e);let o;return a&&a[1]&&(o=+a[1]),o}(),i={},s=e=>{const{callbackId:a,error:o,result:t}=e;void 0!==a&&i[a]&&(o?i[a](o):i[a](null,t),delete i[a])},c=e=>{const a=e.data;let o=a;try{"string"==typeof a&&(o=JSON.parse(a))}catch(e){}s(o)},r=navigator.userAgent;r.indexOf("AlipayClient")>-1&&r.indexOf("MiniProgram")>-1?o="my":r.toLowerCase().indexOf("miniprogram")>-1?o=r.indexOf("QQ")>-1?"qq":"wx":r.indexOf("swan/")>-1?o="swan":r.indexOf("toutiao")>-1&&(o="tt"),window.ReactNativeWebView?(o="rn",window.mpxWebviewMessageCallback=s):(o="web",window.addEventListener("message",c,!1));let w=!1;function d(a){w?a():e.then(()=>{w=!0,a()})}const g={config(e){"wx"===o?d(()=>{window.wx&&window.wx.config(e)}):console.warn("\u975e\u5fae\u4fe1\u73af\u5883\u4e0d\u9700\u8981\u914d\u7f6econfig")}};const p=()=>{const e={wx:{keyName:"miniProgram",api:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","postMessage","getEnv"]},tt:{keyName:"miniProgram",api:["redirectTo","navigateTo","switchTab","reLaunch","navigateBack","setSwipeBackModeSync","postMessage","getEnv","checkJsApi","chooseImage","compressImage","previewImage","uploadFile","getNetworkType","openLocation","getLocation"]},swan:{keyName:"webView",api:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","getEnv","postMessage"]},qq:{keyName:"miniProgram",api:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","getEnv","postMessage"]}}[o]||{},a={wx:["checkJSApi","chooseImage","previewImage","uploadImage","downloadImage","getLocalImgData","startRecord","stopRecord","onVoiceRecordEnd","playVoice","pauseVoice","stopVoice","onVoicePlayEnd","uploadVoice","downloadVoice","translateVoice","getNetworkType","openLocation","getLocation","startSearchBeacons","stopSearchBeacons","onSearchBeacons","scanQRCode","chooseCard","addCard","openCard"],my:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","chooseImage","previewImage","getLocation","openLocation","alert","showLoading","hideLoading","getNetworkType","startShare","tradePay","postMessage","onMessage","getEnv"],swan:["makePhoneCall","setClipboardData","getNetworkType","openLocation","getLocation","chooseLocation","chooseImage","previewImage","openShare","navigateToSmartProgram"],web:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","getEnv","postMessage","getLocation","invoke"],rn:["navigateTo","navigateBack","switchTab","reLaunch","redirectTo","getEnv","postMessage","getLocation","invoke"],tt:[]}[o]||[];(e.api||[]).forEach(a=>{g[a]=(...t)=>{d(()=>{window[o][e.keyName][a](...t)})}}),a.forEach(e=>{g[e]=(...a)=>{"web"===o||"rn"===o?function(e,...a){"invoke"===e&&(e=a[0],a=a.slice(1));const o=a[0]||{};if("getEnv"!==e){const s=++t;i[s]=(e,a)=>{e?(o.fail&&o.fail(e),o.complete&&o.complete(e)):(o.success&&o.success(a),o.complete&&o.complete(a)),delete i[s]};const c={type:e,callbackId:t,args:a};void 0!==n&&(c.clientUid=n),window.ReactNativeWebView?window.ReactNativeWebView.postMessage&&window.ReactNativeWebView.postMessage(JSON.stringify(c)):window.parent.postMessage&&window.parent.postMessage(JSON.stringify(c),"*")}else{let e={webapp:!0};window.ReactNativeWebView&&(e={reactNative:!0}),o(e)}}(e,...a):d("wx"===o?()=>{window[o]&&window[o].ready(()=>{window[o][e](...a)})}:()=>{window[o][e](...a)})}})};e="web"!==o&&"rn"!==o?a[o].url?function(e,{time:a=5e3,crossOrigin:o=!1}={}){return Promise.race([new Promise((a,t)=>{const n=document.createElement("script");n.type="text/javascript",n.async="async",o&&(n.crossOrigin="anonymous"),n.onload=n.onreadystatechange=function(){this.readyState&&!/^(loaded|complete)$/.test(this.readyState)||(a(),n.onload=n.onreadystatechange=null)},n.onerror=function(){t(new Error(`load ${e} error`)),n.onerror=null},n.src=e,document.getElementsByTagName("head")[0].appendChild(n)}),new Promise((o,t)=>{setTimeout(()=>{t(new Error(`load ${e} timeout`))},a)})])}(a[o].url):Promise.reject(new Error("\u672a\u627e\u5230\u5bf9\u5e94\u7684sdk")):Promise.resolve(),p();export default g; \ No newline at end of file diff --git a/packages/webview-bridge/dist/webviewbridge.esm.js b/packages/webview-bridge/dist/webviewbridge.esm.js index f7c3d3d28..69ea04184 100644 --- a/packages/webview-bridge/dist/webviewbridge.esm.js +++ b/packages/webview-bridge/dist/webviewbridge.esm.js @@ -75,6 +75,31 @@ var env = null; var callbackId = 0; var clientUid = getMpxWebViewId(); var callbacks = {}; +var runCallback = function runCallback(msgData) { + var callbackId = msgData.callbackId, + error = msgData.error, + result = msgData.result; + if (callbackId !== undefined && callbacks[callbackId]) { + if (error) { + callbacks[callbackId](error); + } else { + callbacks[callbackId](null, result); + } + delete callbacks[callbackId]; + } +}; +var eventListener = function eventListener(event) { + // 接收web-view的回调 + var data = event.data; + var msgData = data; + try { + if (typeof data === 'string') { + msgData = JSON.parse(data); + } + } catch (e) {} + runCallback(msgData); +}; + // 环境判断逻辑 var systemUA = navigator.userAgent; if (systemUA.indexOf('AlipayClient') > -1 && systemUA.indexOf('MiniProgram') > -1) { @@ -85,33 +110,16 @@ if (systemUA.indexOf('AlipayClient') > -1 && systemUA.indexOf('MiniProgram') > - env = 'swan'; } else if (systemUA.indexOf('toutiao') > -1) { env = 'tt'; +} +if (window.ReactNativeWebView) { + env = 'rn'; + window.mpxWebviewMessageCallback = runCallback; } else { env = 'web'; - window.addEventListener('message', function (event) { - // 接收web-view的回调 - var data = event.data; - var msgData = data; - try { - if (typeof data === 'string') { - msgData = JSON.parse(data); - } - } catch (e) {} - var _msgData = msgData, - callbackId = _msgData.callbackId, - error = _msgData.error, - result = _msgData.result; - if (callbackId !== undefined && callbacks[callbackId]) { - if (error) { - callbacks[callbackId](error); - } else { - callbacks[callbackId](null, result); - } - delete callbacks[callbackId]; - } - }, false); + window.addEventListener('message', eventListener, false); } var initWebviewBridge = function initWebviewBridge() { - sdkReady = env !== 'web' ? SDK_URL_MAP[env].url ? loadScript(SDK_URL_MAP[env].url) : Promise.reject(new Error('未找到对应的sdk')) : Promise.resolve(); + sdkReady = env !== 'web' && env !== 'rn' ? SDK_URL_MAP[env].url ? loadScript(SDK_URL_MAP[env].url) : Promise.reject(new Error('未找到对应的sdk')) : Promise.resolve(); getWebviewApi(); }; var webviewSdkready = false; @@ -146,7 +154,7 @@ function postMessage(type) { type = extraData[0]; extraData = extraData.slice(1); } - var data = extraData[0]; + var data = extraData[0] || {}; if (type !== 'getEnv') { var currentCallbackId = ++callbackId; callbacks[currentCallbackId] = function (err, res) { @@ -173,9 +181,15 @@ function postMessage(type) { window.parent.postMessage && window.parent.postMessage(JSON.stringify(postParams), '*'); } } else { - data({ + var result = { webapp: true - }); + }; + if (window.ReactNativeWebView) { + result = { + reactNative: true + }; + } + data(result); } } var getWebviewApi = function getWebviewApi() { @@ -201,7 +215,8 @@ var getWebviewApi = function getWebviewApi() { wx: ['checkJSApi', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getLocalImgData', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice', 'downloadVoice', 'translateVoice', 'getNetworkType', 'openLocation', 'getLocation', 'startSearchBeacons', 'stopSearchBeacons', 'onSearchBeacons', 'scanQRCode', 'chooseCard', 'addCard', 'openCard'], my: ['navigateTo', 'navigateBack', 'switchTab', 'reLaunch', 'redirectTo', 'chooseImage', 'previewImage', 'getLocation', 'openLocation', 'alert', 'showLoading', 'hideLoading', 'getNetworkType', 'startShare', 'tradePay', 'postMessage', 'onMessage', 'getEnv'], swan: ['makePhoneCall', 'setClipboardData', 'getNetworkType', 'openLocation', 'getLocation', 'chooseLocation', 'chooseImage', 'previewImage', 'openShare', 'navigateToSmartProgram'], - web: ['navigateTo', 'navigateBack', 'switchTab', 'reLaunch', 'redirectTo', 'getEnv', 'postMessage', 'getLoadError', 'getLocation', 'invoke'], + web: ['navigateTo', 'navigateBack', 'switchTab', 'reLaunch', 'redirectTo', 'getEnv', 'postMessage', 'getLocation', 'invoke'], + rn: ['navigateTo', 'navigateBack', 'switchTab', 'reLaunch', 'redirectTo', 'getEnv', 'postMessage', 'getLocation', 'invoke'], tt: [] }; var multiApi = multiApiMap[env] || {}; @@ -223,7 +238,7 @@ var getWebviewApi = function getWebviewApi() { for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } - if (env === 'web') { + if (env === 'web' || env === 'rn') { postMessage.apply(void 0, [item].concat(args)); } else if (env === 'wx') { runWebviewApiMethod(function () { diff --git a/packages/webview-bridge/dist/webviewbridge.js b/packages/webview-bridge/dist/webviewbridge.js index e1a097571..48a40f8bb 100644 --- a/packages/webview-bridge/dist/webviewbridge.js +++ b/packages/webview-bridge/dist/webviewbridge.js @@ -81,6 +81,31 @@ var callbackId = 0; var clientUid = getMpxWebViewId(); var callbacks = {}; + var runCallback = function runCallback(msgData) { + var callbackId = msgData.callbackId, + error = msgData.error, + result = msgData.result; + if (callbackId !== undefined && callbacks[callbackId]) { + if (error) { + callbacks[callbackId](error); + } else { + callbacks[callbackId](null, result); + } + delete callbacks[callbackId]; + } + }; + var eventListener = function eventListener(event) { + // 接收web-view的回调 + var data = event.data; + var msgData = data; + try { + if (typeof data === 'string') { + msgData = JSON.parse(data); + } + } catch (e) {} + runCallback(msgData); + }; + // 环境判断逻辑 var systemUA = navigator.userAgent; if (systemUA.indexOf('AlipayClient') > -1 && systemUA.indexOf('MiniProgram') > -1) { @@ -91,33 +116,16 @@ env = 'swan'; } else if (systemUA.indexOf('toutiao') > -1) { env = 'tt'; + } + if (window.ReactNativeWebView) { + env = 'rn'; + window.mpxWebviewMessageCallback = runCallback; } else { env = 'web'; - window.addEventListener('message', function (event) { - // 接收web-view的回调 - var data = event.data; - var msgData = data; - try { - if (typeof data === 'string') { - msgData = JSON.parse(data); - } - } catch (e) {} - var _msgData = msgData, - callbackId = _msgData.callbackId, - error = _msgData.error, - result = _msgData.result; - if (callbackId !== undefined && callbacks[callbackId]) { - if (error) { - callbacks[callbackId](error); - } else { - callbacks[callbackId](null, result); - } - delete callbacks[callbackId]; - } - }, false); + window.addEventListener('message', eventListener, false); } var initWebviewBridge = function initWebviewBridge() { - sdkReady = env !== 'web' ? SDK_URL_MAP[env].url ? loadScript(SDK_URL_MAP[env].url) : Promise.reject(new Error('未找到对应的sdk')) : Promise.resolve(); + sdkReady = env !== 'web' && env !== 'rn' ? SDK_URL_MAP[env].url ? loadScript(SDK_URL_MAP[env].url) : Promise.reject(new Error('未找到对应的sdk')) : Promise.resolve(); getWebviewApi(); }; var webviewSdkready = false; @@ -152,7 +160,7 @@ type = extraData[0]; extraData = extraData.slice(1); } - var data = extraData[0]; + var data = extraData[0] || {}; if (type !== 'getEnv') { var currentCallbackId = ++callbackId; callbacks[currentCallbackId] = function (err, res) { @@ -179,9 +187,15 @@ window.parent.postMessage && window.parent.postMessage(JSON.stringify(postParams), '*'); } } else { - data({ + var result = { webapp: true - }); + }; + if (window.ReactNativeWebView) { + result = { + reactNative: true + }; + } + data(result); } } var getWebviewApi = function getWebviewApi() { @@ -207,7 +221,8 @@ wx: ['checkJSApi', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getLocalImgData', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice', 'downloadVoice', 'translateVoice', 'getNetworkType', 'openLocation', 'getLocation', 'startSearchBeacons', 'stopSearchBeacons', 'onSearchBeacons', 'scanQRCode', 'chooseCard', 'addCard', 'openCard'], my: ['navigateTo', 'navigateBack', 'switchTab', 'reLaunch', 'redirectTo', 'chooseImage', 'previewImage', 'getLocation', 'openLocation', 'alert', 'showLoading', 'hideLoading', 'getNetworkType', 'startShare', 'tradePay', 'postMessage', 'onMessage', 'getEnv'], swan: ['makePhoneCall', 'setClipboardData', 'getNetworkType', 'openLocation', 'getLocation', 'chooseLocation', 'chooseImage', 'previewImage', 'openShare', 'navigateToSmartProgram'], - web: ['navigateTo', 'navigateBack', 'switchTab', 'reLaunch', 'redirectTo', 'getEnv', 'postMessage', 'getLoadError', 'getLocation', 'invoke'], + web: ['navigateTo', 'navigateBack', 'switchTab', 'reLaunch', 'redirectTo', 'getEnv', 'postMessage', 'getLocation', 'invoke'], + rn: ['navigateTo', 'navigateBack', 'switchTab', 'reLaunch', 'redirectTo', 'getEnv', 'postMessage', 'getLocation', 'invoke'], tt: [] }; var multiApi = multiApiMap[env] || {}; @@ -229,7 +244,7 @@ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } - if (env === 'web') { + if (env === 'web' || env === 'rn') { postMessage.apply(void 0, [item].concat(args)); } else if (env === 'wx') { runWebviewApiMethod(function () { diff --git a/packages/webview-bridge/dist/webviewbridge.min.js b/packages/webview-bridge/dist/webviewbridge.min.js index 7ac85a8e7..a8a6c7b98 100644 --- a/packages/webview-bridge/dist/webviewbridge.min.js +++ b/packages/webview-bridge/dist/webviewbridge.min.js @@ -3,4 +3,4 @@ * (c) 2024 @mpxjs team * @license Apache */ -var e,o;e=this,o=function(){"use strict";var e,o,a,t,n=Object.assign({wx:{url:"https://res.wx.qq.com/open/js/jweixin-1.3.2.js"},qq:{url:"https://qqq.gtimg.cn/miniprogram/webview_jssdk/qqjssdk-1.0.0.js"},my:{url:"https://appx/web-view.min.js"},swan:{url:"https://b.bdstatic.com/searchbox/icms/searchbox/js/swan-2.0.4.js"},tt:{url:"https://lf3-cdn-tos.bytegoofy.com/obj/goofy/developer/jssdk/jssdk-1.2.1.js"}},window.sdkUrlMap),i=null,r=0,c=(a=location.href,(t=/mpx_webview_id=(\d+)/g.exec(a))&&t[1]&&(o=+t[1]),o),s={},d=navigator.userAgent;d.indexOf("AlipayClient")>-1&&d.indexOf("MiniProgram")>-1?i="my":d.toLowerCase().indexOf("miniprogram")>-1?i=d.indexOf("QQ")>-1?"qq":"wx":d.indexOf("swan/")>-1?i="swan":d.indexOf("toutiao")>-1?i="tt":(i="web",window.addEventListener("message",(function(e){var o=e.data,a=o;try{"string"==typeof o&&(a=JSON.parse(o))}catch(e){}var t=a,n=t.callbackId,i=t.error,r=t.result;void 0!==n&&s[n]&&(i?s[n](i):s[n](null,r),delete s[n])}),!1));var g=!1;function w(o){g?o():e.then((function(){g=!0,o()}))}var p={config:function(e){"wx"===i?w((function(){window.wx&&window.wx.config(e)})):console.warn("\u975e\u5fae\u4fe1\u73af\u5883\u4e0d\u9700\u8981\u914d\u7f6econfig")}};function l(e){for(var o=arguments.length,a=new Array(o>1?o-1:0),t=1;t1&&void 0!==arguments[1]?arguments[1]:{},a=o.time,t=void 0===a?5e3:a,n=o.crossOrigin,i=void 0!==n&&n;function r(){return new Promise((function(o,a){var t=document.createElement("script");t.type="text/javascript",t.async="async",i&&(t.crossOrigin="anonymous"),t.onload=t.onreadystatechange=function(){this.readyState&&!/^(loaded|complete)$/.test(this.readyState)||(o(),t.onload=t.onreadystatechange=null)},t.onerror=function(){a(new Error("load ".concat(e," error"))),t.onerror=null},t.src=e,document.getElementsByTagName("head")[0].appendChild(t)}))}function c(){return new Promise((function(o,a){setTimeout((function(){a(new Error("load ".concat(e," timeout")))}),t)}))}return Promise.race([r(),c()])}(n[i].url):Promise.reject(new Error("\u672a\u627e\u5230\u5bf9\u5e94\u7684sdk")):Promise.resolve(),m(),p},"object"==typeof exports&&"undefined"!=typeof module?module.exports=o():"function"==typeof define&&define.amd?define(o):(e=e||self).mpx=o(); \ No newline at end of file +var e,a;e=this,a=function(){"use strict";var e,a,o,t,n=Object.assign({wx:{url:"https://res.wx.qq.com/open/js/jweixin-1.3.2.js"},qq:{url:"https://qqq.gtimg.cn/miniprogram/webview_jssdk/qqjssdk-1.0.0.js"},my:{url:"https://appx/web-view.min.js"},swan:{url:"https://b.bdstatic.com/searchbox/icms/searchbox/js/swan-2.0.4.js"},tt:{url:"https://lf3-cdn-tos.bytegoofy.com/obj/goofy/developer/jssdk/jssdk-1.2.1.js"}},window.sdkUrlMap),i=null,r=0,c=(o=location.href,(t=/mpx_webview_id=(\d+)/g.exec(o))&&t[1]&&(a=+t[1]),a),s={},d=function(e){var a=e.callbackId,o=e.error,t=e.result;void 0!==a&&s[a]&&(o?s[a](o):s[a](null,t),delete s[a])},w=navigator.userAgent;w.indexOf("AlipayClient")>-1&&w.indexOf("MiniProgram")>-1?i="my":w.toLowerCase().indexOf("miniprogram")>-1?i=w.indexOf("QQ")>-1?"qq":"wx":w.indexOf("swan/")>-1?i="swan":w.indexOf("toutiao")>-1&&(i="tt"),window.ReactNativeWebView?(i="rn",window.mpxWebviewMessageCallback=d):(i="web",window.addEventListener("message",(function(e){var a=e.data,o=a;try{"string"==typeof a&&(o=JSON.parse(a))}catch(e){}d(o)}),!1));var g=!1;function p(a){g?a():e.then((function(){g=!0,a()}))}var l={config:function(e){"wx"===i?p((function(){window.wx&&window.wx.config(e)})):console.warn("\u975e\u5fae\u4fe1\u73af\u5883\u4e0d\u9700\u8981\u914d\u7f6econfig")}};function v(e){for(var a=arguments.length,o=new Array(a>1?a-1:0),t=1;t1&&void 0!==arguments[1]?arguments[1]:{},o=a.time,t=void 0===o?5e3:o,n=a.crossOrigin,i=void 0!==n&&n;function r(){return new Promise((function(a,o){var t=document.createElement("script");t.type="text/javascript",t.async="async",i&&(t.crossOrigin="anonymous"),t.onload=t.onreadystatechange=function(){this.readyState&&!/^(loaded|complete)$/.test(this.readyState)||(a(),t.onload=t.onreadystatechange=null)},t.onerror=function(){o(new Error("load ".concat(e," error"))),t.onerror=null},t.src=e,document.getElementsByTagName("head")[0].appendChild(t)}))}function c(){return new Promise((function(a,o){setTimeout((function(){o(new Error("load ".concat(e," timeout")))}),t)}))}return Promise.race([r(),c()])}(n[i].url):Promise.reject(new Error("\u672a\u627e\u5230\u5bf9\u5e94\u7684sdk")):Promise.resolve(),m(),l},"object"==typeof exports&&"undefined"!=typeof module?module.exports=a():"function"==typeof define&&define.amd?define(a):(e=e||self).mpx=a(); \ No newline at end of file diff --git a/packages/webview-bridge/src/index.js b/packages/webview-bridge/src/index.js index 054b022d2..5d11aded1 100644 --- a/packages/webview-bridge/src/index.js +++ b/packages/webview-bridge/src/index.js @@ -31,6 +31,32 @@ let env = null let callbackId = 0 const clientUid = getMpxWebViewId() const callbacks = {} + +const runCallback = (msgData) => { + const { callbackId, error, result } = msgData + if (callbackId !== undefined && callbacks[callbackId]) { + if (error) { + callbacks[callbackId](error) + } else { + callbacks[callbackId](null, result) + } + delete callbacks[callbackId] + } +} + +const eventListener = (event) => { + // 接收web-view的回调 + const data = event.data + let msgData = data + try { + if (typeof data === 'string') { + msgData = JSON.parse(data) + } + } catch (e) { + } + runCallback(msgData) +} + // 环境判断逻辑 const systemUA = navigator.userAgent if (systemUA.indexOf('AlipayClient') > -1 && systemUA.indexOf('MiniProgram') > -1) { @@ -41,32 +67,16 @@ if (systemUA.indexOf('AlipayClient') > -1 && systemUA.indexOf('MiniProgram') > - env = 'swan' } else if (systemUA.indexOf('toutiao') > -1) { env = 'tt' +} if (window.ReactNativeWebView) { + env = 'rn' + window.mpxWebviewMessageCallback = runCallback } else { env = 'web' - window.addEventListener('message', (event) => { - // 接收web-view的回调 - const data = event.data - let msgData = data - try { - if (typeof data === 'string') { - msgData = JSON.parse(data) - } - } catch (e) { - } - const { callbackId, error, result } = msgData - if (callbackId !== undefined && callbacks[callbackId]) { - if (error) { - callbacks[callbackId](error) - } else { - callbacks[callbackId](null, result) - } - delete callbacks[callbackId] - } - }, false) + window.addEventListener('message', eventListener, false) } const initWebviewBridge = () => { - sdkReady = env !== 'web' ? SDK_URL_MAP[env].url ? loadScript(SDK_URL_MAP[env].url) : Promise.reject(new Error('未找到对应的sdk')) : Promise.resolve() + sdkReady = (env !== 'web' && env !== 'rn') ? SDK_URL_MAP[env].url ? loadScript(SDK_URL_MAP[env].url) : Promise.reject(new Error('未找到对应的sdk')) : Promise.resolve() getWebviewApi() } @@ -101,7 +111,7 @@ function postMessage (type, ...extraData) { type = extraData[0] extraData = extraData.slice(1) } - const data = extraData[0] + const data = extraData[0] || {} if (type !== 'getEnv') { const currentCallbackId = ++callbackId callbacks[currentCallbackId] = (err, res) => { @@ -128,9 +138,15 @@ function postMessage (type, ...extraData) { window.parent.postMessage && window.parent.postMessage(JSON.stringify(postParams), '*') } } else { - data({ + let result = { webapp: true - }) + } + if (window.ReactNativeWebView) { + result = { + reactNative: true + } + } + data(result) } } @@ -263,7 +279,17 @@ const getWebviewApi = () => { 'redirectTo', 'getEnv', 'postMessage', - 'getLoadError', + 'getLocation', + 'invoke' + ], + rn: [ + 'navigateTo', + 'navigateBack', + 'switchTab', + 'reLaunch', + 'redirectTo', + 'getEnv', + 'postMessage', 'getLocation', 'invoke' ], @@ -281,7 +307,7 @@ const getWebviewApi = () => { }) singleApi.forEach((item) => { webviewBridge[item] = (...args) => { - if (env === 'web') { + if (env === 'web' || env === 'rn') { postMessage(item, ...args) } else if (env === 'wx') { runWebviewApiMethod(() => {