uniapp微信小程序webview和h5數(shù)據(jù)通信代碼示例
前言
項(xiàng)目是uniapp編寫,因?yàn)槭窍乳_發(fā)了h5和app,小程序是突然要用的,做兼容開發(fā)已經(jīng)來不及,由于微信小程序webview載入h5 因?yàn)橥ㄐ疟仨氁厥庀拗疲ňW(wǎng)頁向小程序 postMessage 時(shí),會(huì)在以下特定時(shí)機(jī)觸發(fā)并收到消息:小程序后退、組件銷毀、分享、復(fù)制鏈接(2.31.1)。e.detail = { data },data是多次 postMessage 的參數(shù)組成的數(shù)組。),不能滿足使用,所以搞了一套特別low的通信機(jī)制,缺點(diǎn)是通信時(shí)候會(huì)有一個(gè)loading的過渡頁面
業(yè)務(wù)邏輯大致為:
1、微信小程序webview訪問h5帶參數(shù)的url,獲取初始的參數(shù),可以攜帶頁面參數(shù)或者登錄token等,通過reciver接受h5返回的參數(shù)。
2、h5通過一個(gè)中間html頁面存儲(chǔ)小程序的通信邏輯,然后在h5頁面通過定時(shí)器一直獲取緩存本地的數(shù)據(jù),根據(jù)數(shù)據(jù)信息執(zhí)行不同的業(yè)務(wù)邏輯
1、微信小程序項(xiàng)目
(1)微信小程序項(xiàng)目
index.vue
<template> <web-view v-if="src" :src="src" bindload="bindload" binderror="binderror"></web-view> </template> <script lang="ts"> import { cfg } from '@/cfg' import Base64 from '@/utils/Base64' export default { data() { return { src: '', } }, onLoad(e: any) { let loginA = parseInt(e.loginA) console.log(e.loginA) if (loginA) { let self = this wx.login({ success(res: any) { // 自動(dòng)登錄成功 self.msg(Base64.encode64('loginA,' + JSON.stringify([loginA, cfg.mpApp, res.code]))) }, fail(res: any) { // 自動(dòng)登錄失敗 self.msg(Base64.encode64('loginAFail,' + JSON.stringify([loginA, res.errMsg]))) }, }) return } this.msg(e.msg) }, methods: { msg(msg: any) { if (msg) { this.src = cfg.mpUrl + 'static/mpMsg.html?uid=' + cfg.mpid + '&msg=' + msg // this.src = 'http://www.baidu.com/#/' console.log(this.src) // 超時(shí)自動(dòng)關(guān)閉 // @ts-ignore this['$timer'] = setTimeout(() => { this.navBack() }, 3000) return } this.navBack() }, bindload() { console.log('bindload') this.navBack() }, binderror() { console.log('binderror') this.navBack() }, navBack() { let pages = getCurrentPages() if (pages[pages.length - 1].$vm == this) { uni.navigateBack() } // @ts-ignore let timer = this['$timer'] if (timer) { // @ts-ignore delete this['$timer'] clearTimeout(timer) } }, }, } </script> <style></style>
(2)reciver.vue
<template> <view id="preloader"></view> </template> <script lang="ts"> import { App } from '@/store/app' import Base64 from '@/utils/Base64' export default { data() { return { src: '', } }, onLoad(e: any) { try { let msg = e.msg if (msg) { msg = Base64.decode64(msg) let i = msg.indexOf(',') let key = msg let val = '' if (i > 0) { key = msg.substring(0, i) val = msg.substring(i + 1) } // 如果是pc小程序bridge支付,則直接跳轉(zhuǎn)到支付頁面 // const info = uni.getSystemInfoSync() // if ((info?.deviceType == 'pc' || info?.deviceType == 'PC') && key == 'pay') { // uni.redirectTo({ // url: `/pages/index/pay?pay=${Base64.encode64(val)}`, // }) // } else { // uni.navigateBack({ // complete() { // // setTimeout(() => { // App.mpRecieverMsg(key, val) // // }, 100) // }, // }) // } uni.navigateBack({ complete() { // setTimeout(() => { App.mpRecieverMsg(key, val) // }, 100) }, }) return } } catch (e) { console.error(e) } uni.navigateBack() }, methods: {}, } </script> <style scoped> #preloader { position: absolute; width: 30px; height: 30px; background: rgba(253, 87, 17, 1); border-radius: 50px; left: 0; right: 0; top: 0; bottom: 0; margin: auto; -webkit-animation: preloader_1 1.5s infinite linear; -moz-animation: preloader_1 1.5s infinite linear; -ms-animation: preloader_1 1.5s infinite linear; animation: preloader_1 1.5s infinite linear; } #preloader:after { position: absolute; width: 50px; height: 50px; border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); border-left: 10px solid transparent; border-right: 10px solid transparent; border-radius: 50px; content: ''; top: -20px; left: -20px; -webkit-animation: preloader_1_after 1.5s infinite linear; -moz-animation: preloader_1_after 1.5s infinite linear; -ms-animation: preloader_1_after 1.5s infinite linear; animation: preloader_1_after 1.5s infinite linear; } @-webkit-keyframes preloader_1 { 0% { -webkit-transform: rotate(0deg); } 50% { -webkit-transform: rotate(180deg); background: #ff4f11; } 100% { -webkit-transform: rotate(360deg); } } @-webkit-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } @-moz-keyframes preloader_1 { 0% { -moz-transform: rotate(0deg); } 50% { -moz-transform: rotate(180deg); background: #ff4f11; } 100% { -moz-transform: rotate(360deg); } } @-moz-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } @-ms-keyframes preloader_1 { 0% { -ms-transform: rotate(0deg); } 50% { -ms-transform: rotate(180deg); background: #ff4f11; } 100% { -ms-transform: rotate(360deg); } } @-ms-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } @keyframes preloader_1 { 0% { transform: rotate(0deg); } 50% { transform: rotate(180deg); background: #ff4f11; } 100% { transform: rotate(360deg); } } @keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } </style>
(3)app.ts
import cfg from '@/cfg' import Base64 from '@/utils/Base64' export const App = { shareData: {}, mpPostMsg(key: string, val?: string, redirect: boolean = true) { const msg = val ? key + ',' + val : key if (redirect) { uni.redirectTo({ url: '/pages/msg/post?msg=' + Base64.encode64(msg) }) } else { uni.navigateTo({ url: '/pages/msg/post?msg=' + Base64.encode64(msg) }) } }, mpRecievers: { userStorageCert(cert: string) { console.log('userCert', cert) if (cert) { uni.setStorageSync(cfg.mpApp + 'userStorageCert', cert) } }, shareAppMessage(v: string) { let share try { share = JSON.parse(v) if (share.path) { // 使用正則表達(dá)式匹配 _i= 后面的字符串 const match1 = share.path.match(/_i=([^&]+)/) // 如果匹配成功,獲取匹配到的字符串 if (match1) { const extractedString = match1[1] share.path = '/pages/index/index?i=' + extractedString console.log(' share.path', share.path) } } } catch (error) {} try { if (share.imageUrl) { share.imageUrl = share.imageUrl.replace(/(w_\d+)|(h_\d+)/g, (match: string) => { if (match.startsWith('w_')) { return 'w_300' } else if (match.startsWith('h_')) { return 'h_300' } }) } } catch (error) {} if (share) { App.shareData = share } }, pay(v: string) { const pay = JSON.parse(v) pay.success = function () { // 需要通知 App.mpPostMsg('pay,1', undefined, false) } // pay.complete = function () { // // 需要通知 // App.mpPostMsg('pay,1', undefined, false) // } pay.fail = function (e: any) { console.log('pay fail ' + JSON.stringify(e)) uni.showToast({ title: '支付失敗', icon: 'none', duration: 2000, }) } // 支付參數(shù) console.log(JSON.stringify(pay)) const info = uni.getSystemInfoSync() // 如果是pc小程序bridge支付,則延遲掉起,防止不顯示支付彈窗 if (info?.deviceType == 'pc' || info?.deviceType == 'PC') { uni.showLoading() setTimeout(() => { uni.hideLoading() wx.requestPayment(pay) }, 1000) } else { wx.requestPayment(pay) } }, bindWx() { wx.login({ success: function (res: any) { let data = '' if (res) { let appid = '' if (cfg.mpApp) { appid = cfg.mpApp } data = JSON.stringify([appid, res.code]) } App.mpPostMsg('bindWx', data, false) }, fail: function (err: any) { console.log('bindWx fail', err) App.mpPostMsg('bindWx', '', false) }, }) }, openLocation(adress: string) { const data = JSON.parse(adress) wx.openLocation({ latitude: Number(data.latitude), longitude: Number(data.longitude), name: data.name, scale: 18, complete: e => { console.log('openLocation complete', e) }, }) console.log('openLocation data', data) }, downloadAndSave(res: string) { const data = JSON.parse(res) const $delay = data['$delay'] if ($delay > 0) { setTimeout(() => { wx.downloadFile({ url: data.url, success: function (res) { wx.openDocument({ filePath: res.tempFilePath, fileType: 'pdf', showMenu: true, }) }, }) }, $delay) } else { wx.downloadFile({ url: data.url, success: function (res) { wx.openDocument({ filePath: res.tempFilePath, fileType: 'pdf', showMenu: true, }) }, }) } }, callFun(res: string) { const data = JSON.parse(res) // @ts-ignore const fun = wx[data['$fun']] if (fun) { delete data['$fun'] const $delay = data['$delay'] if ($delay > 0) { delete data['$delay'] setTimeout(() => { fun.call(wx, data) }, $delay) } else { fun.call(wx, data) } } }, }, mpRecieverMsg(key: string, val?: string) { // @ts-ignore const fun = App.mpRecievers[key] if (fun) { fun(val) return } }, }
(3)Base64.ts
// private property let _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; // private method for UTF-8 encoding let _utf8_encode = function (str: string) { str = str.replace(/\r\n/g, "\n"); let utftext = ""; for (let n = 0; n < str.length; n++) { let c = str.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if ((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; } // private method for UTF-8 decoding let _utf8_decode = function (utftext: string) { let string = ""; let i = 0; let c, c1, c2, c3 c = c1 = c2 = 0; while (i < utftext.length) { c = utftext.charCodeAt(i); if (c < 128) { string += String.fromCharCode(c); i++; } else if ((c > 191) && (c < 224)) { c2 = utftext.charCodeAt(i + 1); string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); i += 2; } else { c2 = utftext.charCodeAt(i + 1); c3 = utftext.charCodeAt(i + 2); string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); i += 3; } } return string; } const Base64 = { // public method for encoding encode(input: string) { let output = ""; let chr1, chr2, chr3, enc1, enc2, enc3, enc4; let i = 0; input = _utf8_encode(input); while (i < input.length) { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4); } return output; }, // public method for decoding decode(input: string) { let output = ""; let chr1, chr2, chr3; let enc1, enc2, enc3, enc4; let i = 0; input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); while (i < input.length) { enc1 = _keyStr.indexOf(input.charAt(i++)); enc2 = _keyStr.indexOf(input.charAt(i++)); enc3 = _keyStr.indexOf(input.charAt(i++)); enc4 = _keyStr.indexOf(input.charAt(i++)); chr1 = (enc1 << 2) | (enc2 >> 4); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr3 = ((enc3 & 3) << 6) | enc4; output = output + String.fromCharCode(chr1); if (enc3 != 64) { output = output + String.fromCharCode(chr2); } if (enc4 != 64) { output = output + String.fromCharCode(chr3); } } output = _utf8_decode(output); return output; }, // 編碼 encode64(str: string, uri: boolean = true) { str = Base64.encode(str); if (uri) { str = str.replace(/[+|=|/]/g, function (word) { switch (word) { case "+": return "-"; case "=": return "_"; case "/": return "."; } return word; }); } return str; }, // 解碼 decode64(str: string, uri: boolean = true) { if (uri) { str = str.replace(/[-|_|.]/g, function (word) { switch (word) { case "-": return "+"; case "_": return "="; case ".": return "/"; } return word; }); } str = Base64.decode(str); return str; }, } export default Base64
index.vue
<template> <web-view :src="src" @message="receiveMessage"> </web-view> </template> <script lang="ts"> import { cfg } from '@/cfg' import { App } from '@/store/app' import Base64 from '@/utils/Base64' export default { data() { return { src: '', srcP: '', shareData: { imageUrl: 'https://yjy.yiyiny.com//static/images/20240122/' + cfg.mpApp + '.png?x-oss-process=image/auto-orient,1/resize,m_fixed,w_100,h_100', }, shareI: '', } }, onLoad(e: any) { // e.scene 生成小程序碼必須是這個(gè)key this.setSrc(cfg.entryUrl, e.i || e.scene) wx.showShareMenu({ withShareTicket: true, menus: ['shareAppMessage'], success(res) { console.log('mixin share success', res ? JSON.stringify(res) : res) }, fail(err) { console.log('mixin share fail', err ? JSON.stringify(err) : err) }, }) }, onShow() { cfg.mpSrcP = this.srcP App.shareData = {} }, onShareAppMessage(res: any) { console.log(res) if (res.from === 'button') { return this.shareData } if (res.from === 'menu') { return this.shareData || {} } }, onShareTimeline() { let data = { title: '一乙藝術(shù)山莊', query: 'id=1', // imageUrl: '', } return data // return axCc.vueSelf.shareData || {}; }, onHide() {}, methods: { setSrc(src: string, shareI?: string) { let cert = uni.getStorageSync(cfg.mpApp + 'userStorageCert') console.log('setSrc src', src) console.log('setSrc shareI', shareI) let i = src.indexOf('#') let j = src.indexOf('?') let srcP = i > 0 && i < j ? src.substring(0, i) : j > 0 ? src.substring(0, j) : src if (srcP && srcP[srcP.length - 1] != '/') { srcP = srcP + '/' } if (i > 0) { cfg.mpUrl = src.substring(0, i) } else { cfg.mpUrl = cfg.entryUrl } console.log('[ cfg.mpUrl ] >', cfg.mpUrl) this.srcP = srcP cfg.mpSrcP = this.srcP src = j > 0 ? src + '&_mpid_=' + cfg.mpid : src + '?_mpid_=' + cfg.mpid if (shareI) { src = src + '&_i=' + shareI // 分享地址拼接 const startIndex = src.indexOf('#') const endIndex = src.indexOf('?') if (startIndex !== -1 && endIndex !== -1) { src = src.substring(0, startIndex) + src.substring(endIndex) console.log(src) } this.shareI = shareI } src = src + '&ver=' + cfg.version if (cert) { src = src + '&_cert_=' + encodeURIComponent(cert) } this.src = src console.log('setSrc this.src', this.src) }, // 監(jiān)聽h5 消息 // { merber 用戶信息 imageUrl 默認(rèn)分享圖 path 分享地址 title:分享標(biāo)題 desc } receiveMessage(e: any) { console.log('receiveMessage333', e) let arr = e?.detail?.data let data = arr && arr.length > 0 ? arr[arr.length - 1] : null let url if (data && data?.merber?.id) { url = data?.path ? data.path : cfg.mpName == 'mp_wdysj' ? 'pages/artisthome/artisthome' : '/pagesShop/shop/wHome' let parms = this.gen(url, false, { mmId: data?.merber.id }, 13050, data?.merber?.id) console.log('data222', data) this.shareData = { path: '/pages/index/index?i=' + parms + '&fk=1', imageUrl: data?.imageUrl ? data.imageUrl : 'https://yjy.yiyiny.com//static/images/20240122/' + cfg.mpApp + '.png?x-oss-process=image/auto-orient,1/resize,m_fixed,w_100,h_100', title: data?.title ? data.title : cfg.mpName, desc: data?.desc ? data.desc : '', query: parms, } } else { wx.hideShareMenu() } }, // 地址加密 gen(uri: string, bind: boolean, reg: any, eid?: number, memberId?: number): string { // 標(biāo)準(zhǔn)編碼 let ps = [memberId, '', false, uri || '', reg || '', eid] for (let i = ps.length - 1; i >= 0; i--) { if (ps[i]) { let del = ps.length - i - 1 if (del > 0) { ps.splice(i + 1, del) } break } } let _ps: any = ps _ps[0] = _ps[0] || '' if (bind) { _ps[2] = uri _ps[3] = '' } else { _ps[2] = '' } return Base64.encode64(JSON.stringify(ps)) }, }, } </script> <style></style>
cfg.ts
export const cfg = { mpApp: 'mp_wdysj', //一乙藝術(shù)商城 mpName: '一乙藝術(shù)商城', mpUrl: 'https://p.yiyiny.com/xxx/', mpid: '', mpSrcP: '', version: '1.0.8', entryUrl: 'https://p.yiyiny.com/xxx/#/pagesShop/shop/wHome', } const info = uni.getSystemInfoSync() if (!cfg.mpid) { const host = info.host // @ts-ignore if (host && host.appid) { // @ts-ignore cfg.mpid = host.appid } if (!cfg.mpid) { cfg.mpid = cfg.mpApp } } export default cfg
2、h5端
(1)項(xiàng)目初始化時(shí)候h5載入微信sdk
Ainit.ts
// #ifdef H5 let _mpid_; try { let search = <any>( (launcher.h5Search || ab_.route(false, false, false).search) ); _mpid_ = search['_mpid_']; let _cert_ = search['_cert_']; // 獲取小程序傳遞的證書 if (_cert_) { _cert_ = decodeURIComponent(_cert_) User.status.storage.cert = _cert_ } let app = axConfig.webType || 'web' if (Weixin.isWeiXin()) { axCc.Loader().wait("weixinLogin"); ab_.reqJs( axCc.https ? "https://res.wx.qq.com/open/js/jweixin-1.6.0.js" : "http://res.wx.qq.com/open/js/jweixin-1.6.0.js", null, function () { function wxH5() { if (search["code"]) { let parms: Array<string> = [axConfig.webType, search["code"]]; User.loginProvBack( "wx", function (logined) { console.log("微信登陸成功", logined); try { if (logined) { axCc.saveStorage("wxLogined", { token: App.client.plt.headers["atoken"], authPar: User.status.authPar, authParas: User.status.authParas, }); } else { axCc.saveStorage("wxLogined", {}); } } finally { axCc.Loader().done("weixinLogin"); // 微信jsConfig Weixin.wxConfig(); } }, parms, true, true, true ); } else { try { // 關(guān)閉自動(dòng)登錄 // User.autoLogin = false; let wxLogined = axCc.getStorage("wxLogined"); if (wxLogined && wxLogined.token && wxLogined.authParas && wxLogined.authParas[0] === app) { User.loginToken(wxLogined.token, (logined) => { if (logined) { User.status.authPar = wxLogined.authPar; User.status.authParas = wxLogined.authParas; axCc.Loader().done("weixinLogin"); } else { //微信瀏覽器 吊起微信支付必須要獲取openid console.log("掉起微信支付必須要獲取openid"); Weixin.snsapi_base(); } }); } else { //微信瀏覽器 吊起微信支付必須要獲取openid console.log("掉起微信支付必須要獲取openid"); Weixin.snsapi_base(); } } finally { // 微信jsConfig Weixin.wxConfig(); } } } // @ts-ignore if (window.wx) { User.autoLogin = false; try { // @ts-ignore if (typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function") { handleFontSize(); } else { if (document.addEventListener) { document.addEventListener("WeixinJSBridgeReady", handleFontSize, false); // @ts-ignore } else if (document.attachEvent) { // @ts-ignore document.attachEvent("WeixinJSBridgeReady", handleFontSize); // @ts-ignore document.attachEvent("onWeixinJSBridgeReady", handleFontSize); } } function handleFontSize() { // 設(shè)置網(wǎng)頁字體為默認(rèn)大小 // @ts-ignore WeixinJSBridge.invoke('setFontSizeCallback', { 'fontSize': 0 }); // 重寫設(shè)置網(wǎng)頁字體大小的事件 // @ts-ignore WeixinJSBridge.on('menu:setfont', function () { // @ts-ignore WeixinJSBridge.invoke('setFontSizeCallback', { 'fontSize': 0 }); }); } // @ts-ignore if (wx.miniProgram) { // @ts-ignore wx.miniProgram.getEnv((res) => { if (res.miniprogram) { User.status.info.cert = true User.autoLogin = true; // && search['_mpid_'] == "mp_wdysj_shop" if (_mpid_) { if ((_mpid_ == "mp_wdysj_shop" || _mpid_ == "mp_wdysj_yiyi_shop")) { axConfig.pltName = "商城" axConfig.home = "/pagesShop/shop/wHome" App.shopScoreName = '商城' App.client.storeHttp.head('platform', 'mp') axConfig.appProv = _mpid_ axConfig.appEid = 13061 } axConfig.pltApp = _mpid_ User.status.info.app = _mpid_ } // 小程序 Weixin.initWxMpH5(_mpid_, search['ver']) axCc.Loader().done("weixinLogin"); } else { wxH5() } }) return } } catch (e) { console.error(e) } wxH5() } else { axCc.Loader().done("weixinLogin"); } }, undefined ); } else { } } catch (e) { console.error(e); } // #endif
3、Weixin.ts
import ab_ from 'axj-ab_'; //npm install axj-ab_ import Base64 from '../util/Base64'; interface ShareInfo { title: string, desc?: string, link: string, imageUrl?: string, logo?: string,//兼容老項(xiàng)目 imgUrl?: string,//兼容老項(xiàng)目 scene?: string } let weixin = false; let readyReg = false; let wxConfigState = -1; let wxMpH5 = false; let wxMpApp = ''; // let wxMpToken = ''; const Weixin = { initStepsArray: [1000, 2000, 4000, 8000, 16000, 32000, 64000], initI: 0, erred: false, readyed: false, shareInfo: <undefined | ShareInfo>undefined, // 如果wx授權(quán)失敗,則定時(shí)再次獲取授權(quán) wxConfigRe(e?: any) { console.log('wxConfig error ' + e) // alert('wxConfig error ' + JSON.stringify(e)) Weixin.erred = true // @ts-ignore setTimeout(Weixin.wxConfig, Weixin.initI < Weixin.initStepsArray.length ? Weixin.initStepsArray[Weixin.initI++] : Weixin.initStepsArray[Weixin.initStepsArray.length - 1]) }, // 通過config接口注入權(quán)限驗(yàn)證配置 wxConfig() { let authUrl = location.href wxConfigState++ switch (wxConfigState) { case 1: authUrl = Ainit.h5Href break // case 2: // authUrl = location.protocol + '//' + location.host + location.pathname + location.search + location.hash // break default: wxConfigState = 0 break } //調(diào)接口授權(quán)的方法可以自己寫 App.client.plt.reqA(-1, 'C/wxConfig', [axConfig.webType, authUrl], function (err, rep) { console.log('pltClient C/wxConfig err,data:', err, rep) if (rep && rep.appId) { // rep.debug = true rep.jsApiList = [ 'updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareAppMessage', 'onMenuShareTimeline', "getLocation", "scanQRCode", // 'wx-open-launch-weapp', // 'chooseWXPay' ] // rep.debug = true console.log('wxready wx.config') Weixin.erred = false // @ts-ignore wx.config(rep) // @ts-ignore wx.error(Weixin.wxConfigRe) let readyFun = function () { if (Weixin.erred) { return } Weixin.readyed = true } if (readyReg) { setTimeout(readyFun, 1000); } else { readyReg = true // @ts-ignore wx.ready(readyFun) } return; } Weixin.wxConfigRe() }) }, wxShare(v: ShareInfo) { console.log('h5 wxShare alert', v); if (weixin) { // @ts-ignore v = typeof (v) === 'object' ? v : JSON.parse(v) if (!Weixin.readyed) { Weixin.shareInfo = v return } delete Weixin.shareInfo var share = { title: v.title || 'xx', // 分享標(biāo)題 desc: v.desc || '', // 分享描述 link: v.link, // 分享鏈接,該鏈接域名或路徑必須與當(dāng)前頁面對(duì)應(yīng)的公眾號(hào)JS安全域名一致 imgUrl: v.imageUrl || v.logo || v.imgUrl, // 分享圖標(biāo) success: (e) => { console.log('wxShare success ', e) // 顯示微信分享 // @ts-ignore // if (window.WeixinJSBridge) { // // @ts-ignore // window.WeixinJSBridge.call('showOptionMenu') // } if (window.wx && window.wx.showMenuItems) { // @ts-ignore window.wx.showMenuItems({ menuList: [ 'menuItem:share:appMessage', 'menuItem:share:timeline', 'menuItem:favorite', 'menuItem:share:qq', 'menuItem:share:QZone', ] }) } }, fail: function (e) { console.log('wxShare fail', e) } } console.log('updateWx', share) // @ts-ignore wx.updateAppMessageShareData(share) // @ts-ignore wx.updateTimelineShareData(share) // WeixinJSBridge.call("showOptionMenu"); } }, // 靜默授權(quán) snsapi_base() { var backUri = Ainit.h5Href || location.href console.log(backUri) var redirectUri = axConfig.pltH5 + 'static/wx.html?u=' + Base64.encode64(backUri, true) redirectUri = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' + (axConfig.webType == 'wdysjh5' ? 'wxab385cf8a7ec96d8' : 'wx59a0fb7a9bd076e5') + '&redirect_uri=' + encodeURIComponent(redirectUri) + '&response_type=code&scope=snsapi_userinfo&state=1' console.log(redirectUri) location.replace(redirectUri) // setTimeout(() => { // location.replace(redirectUri) // }, 3000); }, isWeiXin() { return weixin; }, isWxMpH5() { return wxMpH5 }, getWxMpApp() { return wxMpApp }, initWxMpH5(mpid: string, ver?: string) { console.log('initWxMpH5 ' + mpid) weixin = false wxMpH5 = true if (mpid) { wxMpApp = mpid } else { console.log('initWxMpH5 no mpid' + location.href) console.log(launcher.h5Href) console.log(launcher.h5Search) } Artist.getReviewVersion(`mp-${ver}`) // 消息通道 setInterval(function () { let msg = localStorage.getItem('_mpmsg_') if (msg) { try { msg = JSON.parse(msg) if (!mpid || msg[0] === mpid) { // 是發(fā)給我的消息 msg = msg[1] msg = Base64.decode64(msg) let i = msg.indexOf(',') if (i > 0) { Weixin.onWxMpMsg(msg.substring(0, i), msg.substring(i + 1)) } else { Weixin.onWxMpMsg(msg, '') } localStorage.removeItem('_mpmsg_') } } catch (e) { console.error(e) localStorage.removeItem('_mpmsg_') } } }, 100) }, onWxMpMsg(key: string, val?: string) { console.log('onWxMpMsg,' + key + ',' + val) if (key == 'pay') { console.log('updatePay,更新支付狀態(tài)' + key) uni.$emit('updatePay', { msg: '更新支付狀態(tài)' }) } // @ts-ignore wx.miniProgram.navigateBack() let fun = Weixin.onWxMpCenter[key] if (fun) { fun(val) } }, forWxMpToken(back: (err?: any) => void) { if (User.status.authPar) { back && back() return } // @ts-ignore let nextT = ab_.nextT() // @ts-ignore Weixin['forWxMpTokenBacks'] = [nextT, back] // @ts-ignore wx.miniProgram.navigateTo({ url: '/pages/msg/post?loginA=' + nextT }) }, onWxMpCenter: { loginA(val: string) { let paras = JSON.parse(val) let nextT = 0 let back: any let loginA = false if (typeof (paras[0]) === 'number') { loginA = true nextT = paras[0] paras = ab_.args(paras, 1, paras.length) let backs = Weixin['forWxMpTokenBacks'] if (backs) { delete Weixin['forWxMpTokenBacks'] if (backs[0] === nextT) { back = backs[1] } } } let noRep = nextT && User.state.logined User.loginProvBack('wx', (succ, rep) => { console.log('loginA ', succ, rep) if (succ) { Page.loginSuccBack() if (loginA) { // @ts-ignore wx.miniProgram.navigateBack() } } else if (!User.state.authing && !nextT) { console.log('toLogin--------') Weixin.postWxMpMsg('toLogin') } // 回調(diào) back && back(User.status.authToken ? undefined : rep) }, paras, false, 2, false, noRep) }, loginAFail(val: string) { let paras = JSON.parse(val) let nextT = paras[0] let backs = Weixin['forWxMpTokenBacks'] if (backs) { delete Weixin['forWxMpTokenBacks'] if (backs[0] === nextT) { backs[1] && backs[1](paras[1]) } } }, loginInfo(val: string) { //let loginInfo = JSON.parse(val) let paras = JSON.parse(val) if (User.status.authToken) { paras[1] = User.status.authToken } User.loginProvBack('wx', (succ) => { if (succ) { Page.loginSuccBack() } else if (!User.state.authing) { User.status.authToken = '' } }, paras, true, 2) }, bindWx(val: string) { uni.$emit('updateBindWx', { msg: val }) } }, postWxMpMsg(key: string, val?: string) { console.log('postWxMpMsg,' + key + ',' + val) if (key === 'toLogin') { // ios 微信新用戶第一次登錄 會(huì)導(dǎo)致不執(zhí)行此邏輯 setTimeout(() => { // @ts-ignore wx.miniProgram.navigateTo({ url: '/pages/index/login?t=' + User.status.authToken }) }, 400); return } // if (key === 'toLoginA') { // // @ts-ignore // wx.miniProgram.navigateTo({ url: '/pages/index/login' }) // return // } if (key === 'share') { // @ts-ignore wx.miniProgram.navigateTo({ url: '/pages/msg/share?s=' + val }) return } let msg = val ? (key + ',' + val) : key setTimeout(() => { // @ts-ignore wx.miniProgram.navigateTo({ url: '/pages/msg/reciver?msg=' + Base64.encode64(msg) }) }, 400); console.log('postWxMpMsg.navigateTo'); }, } // #ifdef H5 try { // 微信環(huán)境判斷 let userAgent: any = window.navigator.userAgent.toLowerCase(); weixin = userAgent.match(/MicroMessenger/i) == "micromessenger" && !(window.parent && window.parent !== window); //兼容 微信支付路徑 if (weixin) { let h5Uri = location.href; if (h5Uri.indexOf('/#/') < 0) { // axCc.Loader().wait("weixinHref"); try { h5Uri = location.origin + location.pathname + "#/" + location.search location.href = h5Uri setTimeout(() => { location.reload() }, 1000); axCc.Loader().wait("weixinHref"); } catch (error) { } } } } catch (e) { console.error(e); } // #endif export default Weixin;
4、公共h5跳轉(zhuǎn)頁
<html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1,viewport-fit=cover" /> <title>···</title> <style> #loadingBg { width: 100vw; height: 100vh; position: fixed; z-index: 10000; top: 0; } body { margin: 0px; font-size: 12px; } #preloader { position: absolute; width: 30px; height: 30px; background: rgba(253, 87, 17, 1); border-radius: 50px; left: 0; right: 0; top: 0; bottom: 0; margin: auto; -webkit-animation: preloader_1 1.5s infinite linear; -moz-animation: preloader_1 1.5s infinite linear; -ms-animation: preloader_1 1.5s infinite linear; animation: preloader_1 1.5s infinite linear; } #preloader:after { position: absolute; width: 50px; height: 50px; border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); border-left: 10px solid transparent; border-right: 10px solid transparent; border-radius: 50px; content: ""; top: -20px; left: -20px; -webkit-animation: preloader_1_after 1.5s infinite linear; -moz-animation: preloader_1_after 1.5s infinite linear; -ms-animation: preloader_1_after 1.5s infinite linear; animation: preloader_1_after 1.5s infinite linear; } @-webkit-keyframes preloader_1 { 0% { -webkit-transform: rotate(0deg); } 50% { -webkit-transform: rotate(180deg); background: #ff4f11; } 100% { -webkit-transform: rotate(360deg); } } @-webkit-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } @-moz-keyframes preloader_1 { 0% { -moz-transform: rotate(0deg); } 50% { -moz-transform: rotate(180deg); background: #ff4f11; } 100% { -moz-transform: rotate(360deg); } } @-moz-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } @-ms-keyframes preloader_1 { 0% { -ms-transform: rotate(0deg); } 50% { -ms-transform: rotate(180deg); background: #ff4f11; } 100% { -ms-transform: rotate(360deg); } } @-ms-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } @keyframes preloader_1 { 0% { transform: rotate(0deg); } 50% { transform: rotate(180deg); background: #ff4f11; } 100% { transform: rotate(360deg); } } @keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } </style> </head> <script> function getPara(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r != null) { return unescape(r[2]); } return null; } let uid = getPara("uid"); let msg = getPara("msg"); if (msg) { localStorage.setItem("_mpmsg_", JSON.stringify([uid, msg])); } </script> <body> <div id="loadingBg"> <div id="preloader"></div> <!-- <div>加載中</div> --> </div> </body> </html>
總結(jié)
到此這篇關(guān)于uniapp微信小程序webview和h5數(shù)據(jù)通信的文章就介紹到這了,更多相關(guān)uniapp小程序webview和h5數(shù)據(jù)通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3+element-plus動(dòng)態(tài)路由菜單示例代碼
這篇文章主要介紹了vue3+element-plus動(dòng)態(tài)路由菜單示例代碼,代碼簡單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-11-11Vue動(dòng)態(tài)擴(kuò)展表頭的表格及數(shù)據(jù)方式(數(shù)組嵌套對(duì)象)
這篇文章主要介紹了Vue動(dòng)態(tài)擴(kuò)展表頭的表格及數(shù)據(jù)方式(數(shù)組嵌套對(duì)象),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03在Vue中導(dǎo)入并讀取Excel數(shù)據(jù)的操作步驟
在工作中遇到需要前端上傳excel文件獲取到相應(yīng)數(shù)據(jù)處理之后傳給后端并且展示上傳文件的數(shù)據(jù),所以本文就來給大家介紹一下Vue中導(dǎo)入并讀取Excel數(shù)據(jù)的操作步驟,需要的朋友可以參考下2023-08-08解決修復(fù)報(bào)錯(cuò)Error in render:TypeError:Cannot read&n
這篇文章主要介紹了解決修復(fù)報(bào)錯(cuò)Error in render:TypeError:Cannot read properties of undefined(reading ‘ipconfig‘)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03Vue3 的響應(yīng)式和以前有什么區(qū)別,Proxy 無敵?
這篇文章主要介紹了Vue3 的響應(yīng)式和以前有什么區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05vue-element-admin中node-sass換成dart-sass,安裝依賴報(bào)code?128多種問題的解決
這篇文章主要介紹了vue-element-admin中node-sass換成dart-sass,安裝依賴報(bào)code?128多種問題的解決方法,本文給大家分享問題原因分析及解決方法,需要的朋友可以參考下2023-02-02