Vue3+Vite H5项目中实现跳转微信小程序

2,869 阅读5分钟

前言

最近公司业务需求是要在其他一些app应用上实现点击跳转微信小程序,还要实现一些定制化的页面。原先的需求只是要在微信中有个跳转的H5链接然后跳转小程序,这个我直接用一个原生的index.html页面就搞定了,现在要脱离微信平台而且还要定制化,那原生JS写就显得有些捉襟见肘了,于是我上了框架,但在框架中也是踩了不少的坑。

需求

我这边跳转到微信小程序有两种情况,第一种是微信扫一扫扫描二维码,显示H5页面点击后跳转小程序,另一种则是在非微信端中的H5页面打开微信小程序页面。

第一种情况

这个我们可以使用微信官方提供的开放标签wx-open-launch-weapp做跳转,根据官方文档,使用该标签有两种方式: image.png 我这边是没有已认证的服务号的,所以只能使用方式二,如果有认证的服务号,那就要简单很多,前端只需要调用接口,获取签名,根据微信官方文档操作即可调用这个开放标签了。方式二则需要使用小程序云开发,只要将网页托管到云开发静态网站上就可以直接使用,不需要通过服务端获取签名的操作。

第二种情况

通过非微信端打开微信小程序需要申请微信云环境,然后上传云函数后通过微信官方提供的云函数库跳转到微信小程序。

实现过程

安装项目需要的库

npm install @wxcloud/cloud-sdk --save
npm install weixin-js-sdk --save

`

设备和页面环境判断

/**
 * 判断当前设备是否为手机端
 * @returns {Boolean} 是否手机端打开
 */
export function isMobile(){
    return navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|IEMobile)/i)
}

/**
 * 是否是微信端打开
 */
export function isWx(){
    let ua = navigator.userAgent.toLowerCase()
    let isWxWork = ua.match(/wxwork/i) == 'wxwork'
    return !isWxWork && ua.match(/micromessenger/i) == 'micromessenger'
}

当用户是手机端打开

  1. 页面环境是微信端 image.png image.png 开放标签wx-open-launch-weapp相关属性说明 这里面有个坑就是微信官方文档中给的例子是在template标签中直接用script标签,在项目中这样直接写上vue编译时会报错,这里我用了component标签,用is指定告诉vue是一个script标签,后面的style标签也同理。接下来我们就可以将页面打包后的文件放置到云开发静态网页上发布,用微信访问对应地址就可以实现跳转微信小程序了。 b07fd88155ef4bd97de0c8f784f0c9b.jpg
  • 微信静态网页开通:微信开发者工具-云开发-开通完毕-更多-静态网站开发
  1. 页面环境非微信端 首先,创建一个云开发环境,这个我们在开通静态网页时就创建好了的。下载云函数模版,将下载好的模版中public文件夹放置在cloudfunctions里 image.png
  • 接下来在public文件中的index.js中更改我们需要跳转的小程序具体路径和传递的参数

image.png

  • 然后右键部署到云端

image.png

  • 部署完成后,回到vue项目,这里我做了一下简单的封装,然后暴露出openWeapp方法调用云函数从而打开微信小程序 image.png
  • 在vue文件中 image.png image.png
  • 如果只是从非微信端打开小程序,那么就不用部署在云开发的静态网站上了,这里因为我都需要所以还是部署在云开发上。 8857c02637d15f40e5a17a44624276e.jpg

非手机端打开

提示用户通过链接在手机上打开

vue项目的完整代码

<template>
    <div class="container flex justify-center items-center h-screen">
        <template v-if="isMobile()">
            <wx-open-launch-weapp 
                id="launch-btn"
                env-version="release"
                username="gh_username"
                path="要跳转的小程序具体路径"
                :style="{ display: 'block', position: 'relative' }"
                appid="你的小程序appid"
                @ready="openReady"
                @launch="openLaunch"
                @error="openError"
                v-if="isWxPlat">
                    <component is="script" type="text/wxtag-template" style="display: block;">
                        <component is="style">
                            .openBtn{
                            display:flex;
                            justify-content:center;
                            align-items:center;
                            width:11rem;
                            background-color:#57BE6A;
                            border-radius:0.25rem;
                            color:#fff;
                            font-size:0.875rem;
                            line-height:1.25rem;
                            padding-top:0.5rem;
                            padding-bottom:0.5rem;
                            }
                        </component>
                        <component is="div" class="openBtn">
                            打开小程序
                        </component>
                    </component>
            </wx-open-launch-weapp>
            <div class="w-44 flex justify-center items-center bg-[#57BE6A] rounded text-white text-sm py-2"
                @click="openWeapp(initParams, openParams)" v-else>打开小程序</div>
        </template>
        <template v-else>
            <p>请在手机打开网页链接</p>
        </template>
    </div>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import wx from 'weixin-js-sdk';
import { openWeapp } from '@/assets/js/cloud'
import { isMobile, isWx } from '@/assets/js/tools'
const initParams = {
    // 必填,表示是未登录模式
    identityless: true,
    // 资源方 AppID
    resourceAppid: '小程序appid', // <!-- replace -->
    // 资源方环境 ID
    resourceEnv: '云环境id', // <!-- replace -->
}
const openParams = {
    name: 'public',//云函数名称
    data: {
        action: 'getUrlScheme',//云函数对应的方法名
        query: 'key=value'//传递的参数
    }
}
const isWxPlat = ref(false)
function openReady() {
    console.log('开放标签 ready')
}
function openLaunch() {
    console.log('开放标签 success');
}
function openError(e) {
    console.log('开放标签 fail', e.detail)
}

/**
 * 初始化微信开放标签配置
 */
function initConfig() {
    isWxPlat.value = isWx()
    //如果是手机微信端打开
    if (isWxPlat.value && isMobile()) {
        wx.config({
            // debug: true, // 调试时可开启
            appId: '小程序appid', // <!-- replace -->
            timestamp: 0, // 必填,填任意数字即可
            nonceStr: 'nonceStr', // 必填,填任意非空字符串即可
            signature: 'signature', // 必填,填任意非空字符串即可
            jsApiList: ['chooseImage', 'scanQRCode', 'checkJsApi'], // 必填,随意一个接口即可 
            openTagList: ['wx-open-launch-weapp'], // 填入打开小程序的开放标签名
        })
        wx.ready(() => {
            console.log('完成');

        })
        wx.error((err) => {
            console.log('失败:', err);
            alert(err.errMsg)
        })
    }
}
onMounted(() => {
    initConfig()
})


</script>
import {showLoadingToast,closeToast} from 'vant'
export async function parseCloud(params) {
    const Cloud = () => import('@wxcloud/cloud-sdk')
    let { initCloud } = await Cloud()
    const cloud = initCloud()
    let c = new cloud.Cloud(params)
    await c.init()
    return c
}

export async function openWeapp(initParams,openParams) {
    showLoadingToast({duration:0,message:'请稍候',forbidClick:true})
    let c = await parseCloud(initParams)
    const res = await c.callFunction(openParams)
    closeToast()
    location.href = res.result.openlink
}
import {showLoadingToast,closeToast} from 'vant'
export async function parseCloud(params) {
    const Cloud = () => import('@wxcloud/cloud-sdk')
    let { initCloud } = await Cloud()
    const cloud = initCloud()
    let c = new cloud.Cloud(params)
    await c.init()
    return c
}

export async function openWeapp(initParams,openParams) {
    showLoadingToast({duration:0,message:'请稍候',forbidClick:true})
    let c = await parseCloud(initParams)
    const res = await c.callFunction(openParams)
    closeToast()
    location.href = res.result.openlink
}