需求背景
由于项目是H5的,用户主要是通过微信扫码进入,在微信上操作,并且会有分享操作,这里不做处理的话,另一方收到的就是一段链接而已,不好看,所以想实现卡片式的分享。最终想要实现的效果如下:

技术栈
- vue:3.5.13
- weixin-js-sdk-ts:1.6.1
实现步骤
安装weixin-js-sdk-ts
npm install [email protected]
sdk初始化
查阅微信网页开发 / JS-SDK说明文档,内部提到:

于是我封装了初始化微信的 hooks
,在页面初始化的时候调用并传递当前页面 url
调用后端接口来获取微信初始化所需要的参数:
ts
import wx from "weixin-js-sdk-ts";
import LiveApi from "@/apis/live/index";
/**
* 微信 SDK 初始化钩子
* @author 鹏北海 <[email protected]>
* @since 2025-05-27
*
* @returns {{
* initWechat: (platform_url: string) => Promise<boolean>,
* wx: typeof wx
* }} 返回包含以下成员的对象:
* - initWechat: 异步初始化微信 SDK 配置的方法
* - wx: 微信 JS-SDK 实例
*
* @remarks
* 实现细节:
* - 通过 `LiveApi.getWeChatKey` 获取签名配置
* - 开发环境开启调试模式(根据 import.meta.env.MODE 判断)
* - 初始化配置包含分享功能所需的 `updateAppMessageShareData` API
* - 使用 Promise 包装微信 SDK 的 ready/error 回调机制
*
* @example
* const { initWechat, wx } = useWechat();
* await initWechat('https://example.com');
*
* @see {@link https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html} weixin-js-sdk 说明文档
*/
export function useWechat() {
const initWechat = async (platform_url: string) => {
const { data } = await LiveApi.getWeChatKey(platform_url);
console.log("%c初始化微信SDK配置", "color: green;");
const config: WeixinConfig = {
debug: /* import.meta.env.MODE === "development" */ false, // 开发环境开启调试
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: ["updateAppMessageShareData", "updateTimelineShareData"], // 我需要用到这两个api
openTagList: [],
};
wx.config(config);
return new Promise((resolve, reject) => {
wx.ready(() => {
console.log("%cwx.ready", "color: green;");
resolve(true);
});
wx.error((error) => {
console.log("%cwx.error", "color: red;");
reject(error);
});
});
};
return { initWechat, wx };
}
使用方法:
ts
<script setup lang="ts">
import { useWechat } from "@/hooks/useWechat";
await initWechat(window.location.href);
wx.updateAppMessageShareData({...})
wx.updateTimelineShareData({...})
</script>
响应式配置分享参数
因为实际业务中,调用分享 api
的参数是异步获取的,,所以我又在初始化的基础上封装了一个微信分享的 hooks
,以保证微信分享时,能够获得异步获取到的数据来配置参数:
ts
import { watch } from "vue";
import { useWechat } from "./useWechat";
/**
* 微信分享自定义钩子
* @author 鹏北海 <[email protected]>
* @since 2025-05-27
*
* @param {Object} options - 配置选项
* @param {Function} options.trigger - 触发分享配置更新的观察函数(当返回值变化时触发更新)
* @param {string|function} options.title - 分享标题(支持响应式函数)
* @param {string|function} options.desc - 分享描述(支持响应式函数)
* @param {string|function} [options.imgUrl] - 分享图标URL(支持响应式函数,可选)
* @param {string|function} [options.link] - 微信初始化路径(支持响应式函数)
* @param {Function} [options.onSuccess] - 分享配置成功回调(可选)
* @param {Function} [options.onError] - 分享配置失败/取消回调(可选)
* @returns {{
* startWxShareWatch: () => void
* }} 返回包含以下方法的对象:
* @remarks
* 该钩子使用 Vue 的 `watch` 实现响应式配置更新,通过设置 flush: 'post' 确保
* 在 DOM 更新后执行分享配置。使用前需确保已正确加载微信 JS-SDK。
*
* 注意,分享标题、描述、图标url可以是响应式函数,如果这些数据是异步返回的,
* 请使用响应式函数的形式,保证 hooks 能读取到有效数据
* 并且传递 trigger 函数来触发分享配置更新。否则直接传递字符串形式,并且不用传递 trigger 函数。
*
* @see {@link https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#10} 微信分享
*/
export function useWechatShare(options: {
trigger?: () => unknown;
title: (() => string) | string;
desc?: (() => string) | string;
imgUrl?: (() => string) | string;
link: (() => string) | string;
onSuccess?: () => void;
onError?: () => void;
}) {
const { wx, initWechat } = useWechat();
// 如果没有提供描述,则使用默认值
if (!options.desc) {
console.log(
"缺少描述,使用默认值: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx。",
);
options.desc =
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx。";
}
const startWxShareWatch = async () => {
if (!options.trigger) {
await fun();
} else {
const stop = watch(
options.trigger,
async (_newValue, _oldValue) => {
await fun(stop);
},
{
// 确保在 DOM 更新后执行,避免获取过时的页面 URL
flush: "post",
},
);
}
async function fun(stop?: () => void) {
try {
await initWechat(window.location.href);
console.log("initWechat");
const success = (msg: string) => {
return () => {
console.log(`${msg}分享配置更新成功`);
options.onSuccess?.();
stop?.(); // 配置成功后停止监听
};
};
const cancel = (msg: string) => {
return () => {
console.log(`${msg}分享配置更新取消`);
options.onError?.();
};
};
console.log("============= options =============");
console.log(options);
wx.updateAppMessageShareData({
title: typeof options.title === "function" ? options.title() : options.title,
desc: typeof options.desc === "function" ? options.desc() : options.desc!,
link: typeof options.link === "function" ? options.link() : options.link,
imgUrl: options.imgUrl ? (typeof options.imgUrl === "function" ? options.imgUrl() : options.imgUrl) : "",
success: success("QQ、微信"),
cancel: cancel("QQ、微信"),
});
wx.updateTimelineShareData({
title: typeof options.title === "function" ? options.title() : options.title,
link: options.link ? (typeof options.link === "function" ? options.link() : options.link) : "",
imgUrl: options.imgUrl ? (typeof options.imgUrl === "function" ? options.imgUrl() : options.imgUrl) : "",
success: success("朋友圈、QQ空间"),
cancel: cancel("朋友圈、QQ空间"),
});
} catch (error) {
console.error("微信初始化失败", error);
options.onError?.();
}
}
};
return {
startWxShareWatch,
};
}
使用方式,在每一个需要分享的页面:
ts
<script setup lang="ts">
import { useWechatShare } from "@/hooks/useWechatShare";
import { onMounted } from "vue";
// 初始化微信分享
const { startWxShareWatch } = useWechatShare({
title: () => "标题",
imgUrl: () => "图片url",
desc: "描述",
link: window.location.href, // 分享当前页面
});
// 监听微信分享状态变化
startWxShareWatch();
</script>
而如果分享所需要的数据是接口异步返回的:
ts
<script setup lang="ts">
import { useWechatShare } from "@/hooks/useWechatShare";
const liveReactiveData = reactive({
livePoster: "",
liveTitle: "",
liveDesc: ""
})
// 初始化微信分享
const { startWxShareWatch } = useWechatShare({
trigger: () => liveReactiveData.liveTitle,
title: () => liveReactiveData.liveTitle,
desc: () => liveReactiveData.liveDesc
imgUrl: () => liveReactiveData.livePoster,
link: window.location.href
});
// 监听微信分享状态变化
startWxShareWatch();
onMounted(() => {
// 模拟异步获取数据
setTimeout(() => {
liveReactiveData.liveTitle = "标题";
liveReactiveData.livePoster = "https://xxxxxxxxx.png";
liveReactiveData.liveDesc = "描述";
}, 5000)
})
</script>
大功告成!!!