From 3d3362e4300d49db23de48575d26c8d501fdbfd8 Mon Sep 17 00:00:00 2001 From: Tevin <tingquanren@163.com> Date: Fri, 20 Aug 2021 18:52:00 +0800 Subject: [PATCH] 优化跨端通讯机制,实现从全局接收App通知,并通知页面 --- bases/Pilot.js | 29 +++++++++ common/BridgeTelling.js | 79 ++++++++++++++++++++++++++ bases/Fetcher.js | 8 +- common/Bridge.js | 47 +++++++++++---- 4 files changed, 147 insertions(+), 16 deletions(-) diff --git a/bases/Fetcher.js b/bases/Fetcher.js index e76073e..5d6c443 100644 --- a/bases/Fetcher.js +++ b/bases/Fetcher.js @@ -464,7 +464,7 @@ * @return {String} * @private */ - _stringToCamel(str) { + stringToCamel(str) { let str2 = ''; if (str.indexOf('_') <= 0) { str2 = str; @@ -484,7 +484,7 @@ * @return {String} * @private */ - _stringToUnderline(str) { + stringToUnderline(str) { let str2 = ''; if ((/[A-Z]/).test(str)) { str2 = str.replace(/([A-Z])/g, ($1) => { @@ -514,9 +514,9 @@ // 字符串键名进行转换 else { if (type === 'camel') { - key = this._stringToCamel(p); + key = this.stringToCamel(p); } else if (type === 'underline') { - key = this._stringToUnderline(p); + key = this.stringToUnderline(p); } } // 属性为对象时,递归转换 diff --git a/bases/Pilot.js b/bases/Pilot.js index babc9de..d7d3966 100644 --- a/bases/Pilot.js +++ b/bases/Pilot.js @@ -3,6 +3,7 @@ * @author Tevin */ +import Taro, { getCurrentInstance } from '@tarojs/taro'; import { Fetcher } from './Fetcher'; import { Tools } from '@components/common/Tools'; import project from '@project'; @@ -52,9 +53,37 @@ options.methods[name] = this[name]; } }); + this._bindTaroPage(options); return options; } + _bindTaroPage(options) { + // 非App内嵌模式,不执行 + if (!project.appHybrid) { + return; + } + // 绑定页面实例到Page + const { onLoad, onUnload, onBridge } = options; + const option2 = { + onLoad() { + const instance = getCurrentInstance(); + instance.page.$component = this; + onLoad && onLoad.call(this); + // 绑定 onBridge 到页面实例 + this.$onBridge = onBridge || (() => { + }); + }, + onUnload() { + const instance = getCurrentInstance(); + delete instance.page.$component; + onUnload && onUnload.call(this); + }, + }; + options.onLoad = option2.onLoad; + options.onUnload = option2.onUnload; + delete options.onBridge; + } + /** * 转换静态图片引用 * @param assets diff --git a/common/Bridge.js b/common/Bridge.js index 1c1c5e8..9729423 100644 --- a/common/Bridge.js +++ b/common/Bridge.js @@ -22,6 +22,9 @@ * window.linking('{method:\'methodName\', param:{key2:\'value2\'}, marker:\'mk222at1541994536008\'}'); */ +import { Fetcher } from '@components/bases/Fetcher'; +import { Tools } from '@components/common/Tools'; + export class Bridge { constructor() { @@ -84,16 +87,20 @@ */ _sendLinking(method, param, callback) { // 数据检查 - if (Object.prototype.toString.call(param) !== '[object Object]') { + if (!Tools.isObject(param)) { console.error('$bridge.invoking 需要接受 JSON 对象!'); return; } + // 转换发送参数键名为下划线 + param = this.transKeyName('underline', param); // 如果有回调,转存回调 const name = 'cb' + this._data.count++ + 'at' + Date.now(); this[name] = (res) => { - if (callback && Object.prototype.toString.call(callback) === '[object Function]') { + if (callback && Tools.isFunction(callback)) { if (res) { - const data = typeof res === 'string' ? JSON.parse(res) : res; + let data = typeof res === 'string' ? JSON.parse(res) : res; + // 转换接收参数键名为驼峰 + data = this.transKeyName('camel', data); callback(data); } else { callback(); @@ -117,9 +124,8 @@ */ invoking(method, param, callback) { // param 为函数时 - const trans = param; - if (trans && Object.prototype.toString.call(trans) === '[object Function]') { - callback = trans; + if (param && Tools.isFunction(param)) { + callback = param; param = {}; } if (this._checkLinking()) { @@ -139,20 +145,26 @@ window.telling = (res) => { const data = typeof res === 'string' ? JSON.parse(res) : res; const { method, param, marker } = data; + // 转换接收参数键名为驼峰 + const param2 = this.transKeyName('camel', param); if (this._receives[method]) { + // 有通知回调 if (marker) { - this._receives[method](param, (param2) => { + this._receives[method](param2, (param2) => { + debugger; this._sendTelling(method, param2 || {}, marker); }); - } else { - this._receives[method](param); + } + // 无通知回调 + else { + this._receives[method](param2); } } }; } /** - * 发送响应 + * 回发App通知的响应 * @param {string} method * @param {object} param * @param {string} marker @@ -160,10 +172,12 @@ */ _sendTelling(method, param, marker) { // 数据检查 - if (Object.prototype.toString.call(param) !== '[object Object]') { + if (!Tools.isObject(param)) { console.error('$bridge.register 注册的函数需要接受 JSON 对象!'); return; } + // 转换发送参数键名为下划线 + param = this.transKeyName('underline', param); // 发送 window.aisim.linking(JSON.stringify({ method, @@ -173,7 +187,7 @@ } /** - * 注册接收指令,可供 app 查询 + * 注册接收指令,可接收 app 通知 * @param method * @param callback */ @@ -189,6 +203,15 @@ return platform === 'android' || platform === 'iOS'; } + /** + * 键名转换 + * @param type + * @param json + */ + transKeyName(type, json) { + return Fetcher.prototype.transKeyName(type, json); + } + } // 全局服务实例 diff --git a/common/BridgeTelling.js b/common/BridgeTelling.js new file mode 100644 index 0000000..3517b71 --- /dev/null +++ b/common/BridgeTelling.js @@ -0,0 +1,79 @@ +/** + * BridgeTelling - 跨端通讯,通知接收基类 + * @author Tevin + */ + +import Taro from '@tarojs/taro'; +import { $bridge } from '@components/common/Bridge'; +import { Fetcher } from '@components/bases/Fetcher'; + +export class BridgeTelling { + constructor(tellings) { + this._init(tellings); + } + + _init(tellings) { + tellings.forEach(method => { + const name = Fetcher.prototype.stringToCamel(method); + if (typeof this[name] === 'undefined') { + console.warn('BridgeTelling:未发现“' + method + '”对于接收器!'); + } else { + // 注册App通知接收器 + $bridge.register(method, (res, callback) => { + this[name](method, res, callback); + }); + } + }); + } + + $getCurrentPage() { + const pages = Taro.getCurrentPages(); + return pages[pages.length - 1]; + } + + $getCurrentPageUrl() { + return this.$getCurrentPage().path; + } + + $isCurrentPage(url) { + const pages = Taro.getCurrentPages(); + const curPage = pages[pages.length - 1]; + if (curPage.path.split('?')[0] === url.split('?')[0]) { + return curPage; + } else { + return null; + } + } + + _checkPage(url, callback) { + let curPage = this.$isCurrentPage(url); + if (curPage) { + callback(curPage); + } else { + setTimeout(() => { + this._checkPage(url, callback); + }, 100); + } + } + + $openPage(url, callback) { + const curPage = this.$isCurrentPage(url); + // 需打开的是当前页面 + if (curPage) { + callback(curPage); + } else { + Taro.navigateTo({ + url, + success: () => { + this._checkPage(url, callback); + }, + }); + } + } + + $pageBridge(page, method, res, callback) { + page.$component.$onBridge(method, res, callback); + } + +} + -- Gitblit v1.9.1