vue配置微信开放标签wx-open-launch-app

2,405 阅读1分钟

背景

H5在微信里打开,然后直接唤起APP,为了解决deeplink 在安卓里不能直接唤起APP的问题

官方文档

开发

前置接口请求

// WXOpenApp.js
import Jsonp from 'jsonp';
let wx = '';
if (process.client) {
    wx = require('weixin-js-sdk');
}

class WXOpenApp {
    constructor () {
        this.url = 'https://xxx.xxxx.com/xxx/getSignPackage';
        this.jsApiList = [
            'checkJsApi',
            'onMenuShareTimeline',
            'onMenuShareAppMessage',
            'onMenuShareQQ',
            'onMenuShareQZone',
            'onMenuShareWeibo',
            'hideMenuItems',
            'showMenuItems',
            'hideAllNonBaseMenuItem',
            'showAllNonBaseMenuItem',
            'translateVoice',
            'startRecord',
            'stopRecord',
            'onRecordEnd',
            'playVoice',
            'pauseVoice',
            'stopVoice',
            'uploadVoice',
            'downloadVoice',
            'chooseImage',
            'previewImage',
            'uploadImage',
            'downloadImage',
            'getNetworkType',
            'openLocation',
            'getLocation',
            'hideOptionMenu',
            'showOptionMenu',
            'closeWindow',
            'scanQRCode',
            'chooseWXPay',
            'openProductSpecificView',
            'addCard',
            'chooseCard',
            'openCard'
        ];
    }

    init () {
        if (wx) {
            const $url = encodeURIComponent(location.href.split('#')[0]);
            // 在服务器端实现签名的逻辑
            Jsonp(`${this.url}?url=${$url}`, {}, (err, res) => {
                if (err) {
                    console.log(err);
                } else {
                    const data = res.data;
                    if (res.error_code === '0') {
                        wx.config({
                            debug: false,
                            appId: data.appId,
                            timestamp: data.timestamp,
                            nonceStr: data.nonceStr,
                            signature: data.signature,
                            jsApiList: this.jsApiList,
                            openTagList: ['wx-open-launch-app','wx-open-launch-weapp']
                        });
                        wx.ready(function () {
                        });
                        wx.error(function (res) {
                            console.log('error', res);
                        });
                    }
                }
            });
        }
    }

    static getInstance () {
        if (!this.instance) {
            this.instance = new WXOpenApp();
        }
        return this.instance;
    }
}

export default WXOpenApp;

封装组件

<template>
    <!-- v-if="isShow" 唤起值得买APP -->
    <div
        v-if="isShow"
        id="wxOpenInAPPVui"
        class="wexin-launch-btn"
    >
        <wx-open-launch-app
            :id="id"
            style="width: 100%; height: 100%; display: block;"
            :appid="appid"
            :extinfo="getExtinfo"
        >
            <script type="text/wxtag-template">
                <style>.btn {width:100%;height:65px;background: #fff}</style>
                <button class="btn">App内查看</button>
            </script>
        </wx-open-launch-app>
    </div>
</template>
<script>
    import Vue from 'vue';
    // 忽略自定义元素标签抛出的报错
    Vue.config.ignoredElements = [
        'wx-open-launch-app'
    ];
    let idIndex = 0;
    export default {
        name: 'my-open-label',
        data () {
            idIndex++;
            return {
                id: 'wxopenLanchAppId' + idIndex,
                appid: '', /* 所需跳转的AppID */
                isShow: false
            };
        },
        mounted () {
            this.init();
        },
        props: {
            href: {
                type: String,
                default: ''
            }
        },
        computed: {
            /* eslint-disable vue/no-side-effects-in-computed-properties */
            // 跳转所需额外信息
            getExtinfo () {
                if (this.href.length === 0) {
                    this.isShow = false;
                    return '';
                } else {
                    const reg = new RegExp('[?&]json=([^#]+)');
                    const query = this.href.match(reg);
                    const urlArr = query ? query[1] : null;
                    if (urlArr) {
                        try {
                            const json = JSON.parse(urlArr);
                            // eslint-disable-next-line quotes
                            return `json={}`; /* 这里要跟客户端对接,客户端需要的参数 */
                        } catch (err) {
                            console.log(err);
                            this.isShow = false;
                            return '';
                        }
                    } else {
                        this.isShow = false;
                        return '';
                    }
                }
            }
            /* eslint-enable vue/no-side-effects-in-computed-properties */
        },
        methods: {
            init () {
                // 判断微信打开并且是安卓
                if (/micromessenger/i.test(navigator.userAgent) && /Android/i.test(navigator.userAgent)) {
                    this.isShow = true;
                }
                this.$nextTick(() => {
                    if (this.isShow) {
                        const _this = this;
                        const btn = document.getElementById(this.id);
                        if (!btn) {
                            return;
                        }
                        btn.addEventListener('error', function () {
                            window.location.href = _this.href;
                        });
                    }
                });
            }
        }
    };
</script>
<style lang="scss" scoped>
.wexin-launch-btn {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    overflow: hidden;
    z-index: 1;
}
</style>

使用组件

PS: 注意,这里因为有异步接口,所以在实际表现中,可能页面打开1s之后,点击才能生效

<template>
    <div>
        <my-open-label :href="deeplink"></my-open-label>
    </div>
</template>
<script>
import WXOpenApp from 'WXOpenApp.js'
export default {
    mounted () {
        const wx = WXOpenApp.getInstance();
        wx.init();
    }
}
</script>