WebApp【公共组件库】@前端(For Git Submodule)
Tevin
2021-08-20 3d3362e4300d49db23de48575d26c8d501fdbfd8
优化跨端通讯机制,实现从全局接收App通知,并通知页面
1 files added
3 files modified
163 ■■■■■ changed files
bases/Fetcher.js 8 ●●●● patch | view | raw | blame | history
bases/Pilot.js 29 ●●●●● patch | view | raw | blame | history
common/Bridge.js 47 ●●●● patch | view | raw | blame | history
common/BridgeTelling.js 79 ●●●●● patch | view | raw | blame | history
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);
                        }
                    }
                    // 属性为对象时,递归转换
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
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);
    }
}
// 全局服务实例
common/BridgeTelling.js
New file
@@ -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);
    }
}