首先,请确保已配置JS安全域名并且完成了服务接入,参考文章 h5接微信js-sdk的详细步骤,前端步骤 1 2。
在vue2中,使用方式
第一种:
安装 wx 的 sdk
npm install weixin-js-sdk 或 yarn add weixin-js-sdk 或 pnpm install weixin-js-sdk
安装完成之后,第一种方式是直接在main.js文件中或对应的组件中引入,并且配置需要的功能
想要使用 wx-open-launch-weapp
wx-open-launch-app
必须配置 openTagList
。
import wx from "weixin-js-sdk"; // 在main.js文件中引入
在组件中引入
<template>
<div>
<wx-open-launch-app :appid="appid" :extinfo="extinfo" @error="error" @launch="launch" @ready="ready">
<script type="text/wxtag-template">
<style>
.btn{
color:red;
}
</style>
<button class="btn">按钮</button>
</script>
</wx-open-launch-app>
</div>
</template>
<script>
import wx from "weixin-js-sdk";
export default {
data(){
return {
appid:'',
extinfo:JSON.stringify({'key':'value'})
}
},
created(){
init()
},
methods:{
async init(){
try{
// 即使路由是 history 模式,即没有 # 号时,也可以返回正常的地址
const url =location.href.split('#')[0]
// 这里也可以对url进行加密后传递,请求后端获取签名的接口,返回小程序ID和签名等信息
const {data}=await getSignature({
url:url
})
// 获取到数据之后,将小程序ID等信息配置完整,我这里解构了一层直接获取到了数据,你也可以直接在getSignature方法中解构了返回
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名
jsApiList: [
'showOptionMenu', // 显示右上角菜单接口
'hideOptionMenu', // 隐藏右上角菜单接口
'onMenuShareAppMessage', // 分享给朋友
'onMenuShareTimeline', // 分享到朋友圈
'onMenuShareQQ', // 分享到QQ
'onMenuShareQZone', // 分享到QQ空间
'onMenuShareWeibo', // 分享到微博
'hideMenuItems', // 批量隐藏功能按钮接口
'showMenuItems', // 批量显示功能按钮接口
'hideAllNonBaseMenuItem', // 隐藏所有非基础按钮接口
'showAllNonBaseMenuItem' // 显示所有功能按钮接口
],
// 必填,需要使用的JS接口列表
openTagList: ['wx-open-launch-weapp', 'wx-open-launch-app'] // 可选,需要使用的开放标签列表,例如['wx-open-launch-app']
});
}catch (e) {
console.error('初始化微信SDK出现异常',e)
return false
}
return new Promise((resolve, reject) => {
wx.ready(() => {
console.log('微信环境初始化微信SDK成功')
resolve(true)
})
wx.error((e) => {
console.error('初始化微信SDK失败', e)
reject(false)
})
})
},
async getSignature(params){
// 这里是项目获取签名的接口
// return axios.post('xxx',params)
},
error(e){
console.log('跳转失败',e)
},
launch(data){
console.log('开始跳转',data)
},
ready(){
console.log('准备好了')
}
}
}
</script>
第二种:封装后使用
新建 weChat.js
文件,实现预加载,分享功能封装等功能,在需要的组件中调用 preInit
方法即可。
想要使用 wx-open-launch-weapp
wx-open-launch-app
必须配置 openTagList
// 判断是否是微信环境
function isWeChat(){
return !!navigator.userAgent.match(/MicroMessenger/) && !navigator.userAgent.match(/wxwork/)
}
// 判断是不是企业微信环境
function isWxWork(){
return !!navigator.userAgent.match(/MicroMessenger/) && !!navigator.userAgent.match(/wxwork/)
}
/**
* 等待指定的时间
* @param {number} time 等待的时间 毫秒
* @returns {Promise<void>}
*/
async function wait(time) {
return new Promise((resolve) => {
setTimeout(resolve, time)
})
}
/**
* @typedef {'NO' | 'PENDING' | 'READY'} ReadyState NO: 未初始化, PENDING: 初始化中, READY: 初始化完成
*/
/**
* 存储不同类型的初始化状态
* @type {{symbo: ReadyState}}
*/
const readyStateMap = {}
// 等待初始化的最大时间
const MAX_WAIT_TIME = 3000
// 每次等待的时间
const PER_WAIT_TIME = 100
const wxReady=Symbol('WX')
/**
* 等待初始化完成,如果已经是READY状态或NO状态则直接返回, 如果是PENDING状态则等待一段时间后再返回
* @param {symbol} type
* @returns {Promise<ReadyState>}
*/
export async function waitPending(type) {
let state = getReadyState(type)
if (state === `READY:${location.href.split('#')[0]}` || state === 'NO') return state
// 如果正在初始化中则等待 并按照间隔时间检查是否初始化完成
const times = MAX_WAIT_TIME / PER_WAIT_TIME
for (let i = 0; i < times; i++) {
await wait(PER_WAIT_TIME)
state = getReadyState(type)
if (state === `READY:${location.href.split('#')[0]}`) return state
if (state === 'NO') break
}
return state
}
/**
* 获取初始化状态
* @param {symbol} type 要获取的类型
*/
export function getReadyState(type) {
readyStateMap[type] = readyStateMap[type] || 'NO'
return readyStateMap[type]
}
export function no(type) {
readyStateMap[type] = 'NO'
}
export function pending(type) {
readyStateMap[type] = 'PENDING'
}
export function ready(type) {
// 这里的状态记录,hash没有问题,但是history模式时 location.href.split('#')[0]得到的路径一直在变化,而导致返回的签名不同,在init方法中,判断状态时会被 return
// readyStateMap[type] = 'READY'
readyStateMap[type] = `READY:${location.href.split('#')[0]}`
}
// 创建 script 标签
function loadJS(js){
return new Promise((resolve,reject)=>{
const script=document.createElement('script')
script.src=js
script.onload=resolve
script.onerror=reject
document.head.appendChild(script)
})
}
async function getSignature(params){
// 这里是项目获取签名的接口
// return axios.post('xxx',params)
}
/**
* 分享类型
* @typedef {Object} ShareType
* @property {string} timeline 分享到朋友圈
* @property {string} wechat 分享给微信好友
* @property {string} chat 分享到对话 企微的转发 微信同分享给朋友
* @property {string} qq 分享到QQ
*/
const shareType = {
/**
* 分享到朋友圈
*/
timeline: 'timeline',
/**
* 分享到微信
*/
wechat: 'wechat',
/**
* 分享到对话
*/
chat: 'chat',
/**
* 分享到QQ
*/
qq: 'qq'
}
/**
* 初始化微信SDK
* @param {boolean} [keepWait=true] 默认为true表示如果是pending则会尝试等待 否则不再等待直接返回错误
*/
async function init(keepWait=true){
// 这里先同步获取状态
const state = getReadyState(wxReady)
// if (state === 'READY') return true
if(state === `READY:${location.href.split('#')[0]}`) return true
// 如果是pending 则根据 keepWait判断是继续等待 还是 直接返回
if (state === 'PENDING') {
if (keepWait) {
await waitPending(wxReady)
return init(false)
} else {
return false
}
}
// 判断是不是微信环境,是微信环境则初始化微信SDK
if(isWeChat()){
console.log("当前环境不是微信环境,不在继续初始化微信SDK")
return false
}
console.log("继续初始化微信SDK")
pending(wxReady)
try{
// 在需要调用 JS 接口的页面引入如下 JS 文件,(支持https):https://res.wx.qq.com/open/js/jweixin-1.6.0.js
// 如需进一步提升服务稳定性,当上述资源不可访问时,可访问(支持https):https://res2.wx.qq.com/open/js/jweixin-1.6.0.js。
if(!window.wx){
await loadJS('https://res.wx.qq.com/open/js/jweixin-1.6.0.js')
}
}catch (e) {
console.error("加载微信JS失败",e)
return false
}
const wx=window.wx
console.log('微信环境初始化微信SDK成功')
try{
// 即使路由是 history 模式,即没有 # 号时,也可以返回正常的地址
const url =location.href.split('#')[0]
// 这里也可以对url进行加密后传递,请求后端获取签名的接口,返回小程序ID和签名等信息
const {data}=await getSignature({
url:url
})
// 获取到数据之后,将小程序ID等信息配置完整,我这里解构了一层直接获取到了数据,你也可以直接在getSignature方法中解构了返回
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名
jsApiList: [
'showOptionMenu', // 显示右上角菜单接口
'hideOptionMenu', // 隐藏右上角菜单接口
'onMenuShareAppMessage', // 分享给朋友
'onMenuShareTimeline', // 分享到朋友圈
'onMenuShareQQ', // 分享到QQ
'onMenuShareQZone', // 分享到QQ空间
'onMenuShareWeibo', // 分享到微博
'hideMenuItems', // 批量隐藏功能按钮接口
'showMenuItems', // 批量显示功能按钮接口
'hideAllNonBaseMenuItem', // 隐藏所有非基础按钮接口
'showAllNonBaseMenuItem' // 显示所有功能按钮接口
],
// 必填,需要使用的JS接口列表
// 想要使用 wx-open-launch-weapp wx-open-launch-app 必须配置这项
openTagList: ['wx-open-launch-weapp', 'wx-open-launch-app'] // 可选,需要使用的开放标签列表,例如['wx-open-launch-app']
});
}catch (e) {
no(wxReady)
console.error('初始化微信SDK出现异常',e)
return false
}
return new Promise((resolve, reject) => {
wx.ready(() => {
console.log('微信环境初始化微信SDK成功')
ready(wxReady)
resolve(true)
})
wx.error((e) => {
no(wxReady)
console.error('初始化微信SDK失败', e)
reject(false)
})
})
}
const supportShareType = {
[shareType.timeline]: 'onMenuShareTimeline',
[shareType.wechat]: 'onMenuShareAppMessage',
[shareType.chat]: 'onMenuShareAppMessage',
[shareType.qq]: 'onMenuShareQQ'
}
/**
* 分享选项
* @typedef {Object} ShareOptions
* @property {string} title 分享标题
* @property {string} desc 分享描述
* @property {string} link 分享链接 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
* @property {string} imgUrl 分享图标
* @property {'music' | 'video' | 'link'} type 分享类型,music、video或link,不填默认为link; 分享给朋友时才有该参数
* @property {string} dataUrl 如果type是music或video,则要提供数据链接,默认为空;
* @property {Array<keyof ShareType>} shareType 分享类型
*/
const wxClient = {
/**
* 预加载
*/
preInit: init,
/**
* 分享类型
* @type {ShareType}
*/
shareType,
/**
* 设置分享 支持同时设置多个不同的分享 如同时设置分享到朋友圈和朋友
* @param options {ShareOptions} 分享选项
* @returns {Promise<boolean>}
*/
async share(options) {
if (!(await init())) {
return false
}
return new Promise((resolve, reject) => {
const shareMethods = new Set()
for (const shareType of options.shareType) {
const shareMethod = supportShareType[shareType]
if (shareMethod) {
shareMethods.add(shareMethod)
}
}
const shareMethodsLength = shareMethods.size
let successCount = 0
const success = () => {
console.log('分享成功')
successCount++
if (successCount === shareMethodsLength) {
resolve(true)
}
}
const error = (e) => {
console.error('分享失败', e)
reject(false)
}
for (const shareMethod of shareMethods) {
window.wx[shareMethod]({ ...options, success, cancel: error, error })
}
})
}
}
const wxProxy = new Proxy(wxClient, {
get(target, key) {
// 如果原对象中存在该属性 则直接返回
if (Reflect.has(target, key)) {
return Reflect.get(target, key)
}
return async function(...args) {
await init()
const wx = window.wx
console.log('当前请求的key', key)
if (typeof wx[key] === 'function') {
return wx[key].apply(wx, args)
} else {
return wx[key]
}
}
}
})
export default wxProxy
在组件中调用 preInit
方法,直接在 template
中写 wx-open-launch-app
标签即可。
<template>
<div>
<wx-open-launch-app :appid="appid" :extinfo="extinfo" @error="error" @launch="launch" @ready="ready">
<script type="text/wxtag-template">
<style>
.btn{
color:red;
}
</style>
<button class="btn">按钮</button>
</script>
</wx-open-launch-app>
</div>
</template>
<script>
import Wx from './weChat'
export default {
data(){
return {
appid:'',
extinfo:JSON.stringify({'key':'value'})
}
},
created(){
Wx.preInit()
},
methods:{
error(e){
console.log('跳转失败',e)
},
launch(data){
console.log('开始跳转',data)
},
ready(){
console.log('准备好了')
}
}
}
</script>
在vue3中,使用方式
在vue3中使用时,js逻辑不变,需要注意的是在 template
中,使用方式有所区别。 <script type="text/wxtag-template"></script>
需要使用 component 组件渲染。
<template>
<div>
<wx-open-launch-app :appid="appid" :extinfo="extinfo" @error="error" @launch="launch" @ready="ready">
<component :is="'script'" type="text/wxtag-template">
<div style="color:red;">
按钮
</div>
</component>
</wx-open-launch-app>
</div>
</template>
<script setup>
import wx from "weixin-js-sdk";
import {ref} from 'vue'
// 如果这两个值不会改变可以不用ref
const appid=ref('')
const extinfo=ref(JSON.stringify({'key':'value'}))
const init=async()=>{
try{
// 即使路由是 history 模式,即没有 # 号时,也可以返回正常的地址
const url =location.href.split('#')[0]
// 这里也可以对url进行加密后传递,请求后端获取签名的接口,返回小程序ID和签名等信息
const {data}=await getSignature({
url:url
})
// 获取到数据之后,将小程序ID等信息配置完整,我这里解构了一层直接获取到了数据,你也可以直接在getSignature方法中解构了返回
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名
jsApiList: [
'showOptionMenu', // 显示右上角菜单接口
'hideOptionMenu', // 隐藏右上角菜单接口
'onMenuShareAppMessage', // 分享给朋友
'onMenuShareTimeline', // 分享到朋友圈
'onMenuShareQQ', // 分享到QQ
'onMenuShareQZone', // 分享到QQ空间
'onMenuShareWeibo', // 分享到微博
'hideMenuItems', // 批量隐藏功能按钮接口
'showMenuItems', // 批量显示功能按钮接口
'hideAllNonBaseMenuItem', // 隐藏所有非基础按钮接口
'showAllNonBaseMenuItem' // 显示所有功能按钮接口
],
// 必填,需要使用的JS接口列表
openTagList: ['wx-open-launch-weapp', 'wx-open-launch-app'] // 可选,需要使用的开放标签列表,例如['wx-open-launch-app']
});
}catch (e) {
console.error('初始化微信SDK出现异常',e)
return false
}
return new Promise((resolve, reject) => {
wx.ready(() => {
console.log('微信环境初始化微信SDK成功')
resolve(true)
})
wx.error((e) => {
console.error('初始化微信SDK失败', e)
reject(false)
})
})
}
init()
const getSignature=async (params)=>{
// 这里是项目获取签名的接口
// return axios.post('xxx',params)
}
const error=(e)=>{
console.log('跳转失败',e)
}
const launch=(data)=>{
console.log('开始跳转',data)
}
const ready=()=>{
console.log('准备好了')
}
</script>
此时,控制台会报错,不能识别标签 wx-open-launch-app
,如果是vite项目,需要在vite.config.js文件中配置以下内容。
isCustomElement 是指自定义的标签是什么,解析时会自动忽略当前标签
如果不喜欢在组件中直接引入wx的 sdk,也可以使用上面封装后的方法。
参考文章 vue3中使用 wx-open-launch-app 标签及解决控制台警告的问题
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
return {
plugins: [
vue(
{
template: {
compilerOptions: {
// 忽略wx-open-launch 开头的组件,这些是微信的默认组件
isCustomElement: (tag) => tag.includes('wx-open-launch')
}
}
}
),
],
}
})
参考文章