前言
微信分享主要是可以把我们做的网页分享给好友或者分享到朋友圈,在发送给好友时,展示出来的消息不是一段很丑的网址,而是带着图文描述的特殊模板消息,很多传播性质比较强的网页都会借助这个特性提升传播性。要实现这个功能,需要我们接入微信的JS-SDK,JS-SDK是什么呢?官方文档介绍如下:
微信JS-SDK是微信公众平台 面向网页开发者提供的基于微信内的网页开发工具包。
通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。
可以看到,JS-SDK能做很多事情,那么今天,我们先讨论关于微信分享的细节。如果你还需要实现微信授权登录相关的功能,那么可以查看笔者的这篇分享:
Vue微信开发中授权登录的优雅实现
准备
第一步,不用多说,同样是先熟读一遍官方文档,文档地址如下:
微信开发JS-SDK使用说明文档
这里需要特殊说明的是,在开发之前,需要先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
这个工作一定不能忘,切记切记。
使用JS-SDK还有一个关键的环节,那就是通过config接口注入权限验证配置,而配置中有个signature参数是需要借助服务端获取的,所以咱们开发时依然需要跪舔一波后端伙伴给予支持(全栈的看官就当我没说)。
看完文档的看官们,应该都能梳理出来咱们接入微信分享的具体流程了,笔者梳理如下:
- 引入JS-SDK;
- 通过调用后端接口获取签名,签名算法见该页;
- 调用wx.config方法注入相关配置;
- 调用相关的分享的api,传入对应的分享信息;
实现
这里笔者以实现一个微信漂流瓶功能为例,分享一下编码过程;技术栈采用的是Vue3+typescript,Vue2的开发者还请根据情况做适当调整。
引入JS-SDK
官方文档的描述是引入js-sdk文件,即通过script方式引入,但我们现在是Vue应用,那么能不能通过npm仓库安装通过ESModule方式引入呢?当然是可以的,安装命令如下:
1 2 3 4
| // js版本 yarn add weixin-js-sdk // ts版本 yarn add weixin-js-sdk-ts
|
笔者这里安装的是ts版本, 安装完后,package.json中显示了安装的版本

封装模块
本着功能解耦原则和方便复用,笔者决定单独新建一个文件,专门封装js-sdk相关的功能。在vue3中,当然是封装成hook啦。所以,咱们在hooks目录下,新建了一个useWxSDK.ts
文件;
然后,开始封装第一个方法,即wx.config
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
function initConfig(configInfo) { return new Promise((resolve) => { wx.config({ debug: false, appId: configInfo.appId, timestamp: configInfo.timestamp, nonceStr: configInfo.nonceStr, signature: configInfo.signature, jsApiList: configInfo.jsApiList ?? [ 'chooseImage', 'uploadImage', 'previewImage', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'chooseWXPay', ], openTagList: [], }) wx.ready(() => { resolve(true) }) }) }
|
这里说明一下wx.config方法,为啥要封装为Promise呢?其实可以看到JS-SDK的API设计是比较原始的,我们需要通过wx.ready去注册配置成功后的回调函数,笔者在这里用Promise封装,在ready回调函数里调用Promise.resolve,那么我们在用的时候,就可以通过优雅的then语法来实现配置成功后的操作啦!
接下来封装分享好友和微信朋友圈的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| function setShareInfo(shareInfo,onSuccess, onCancel) { wx.onMenuShareTimeline({ title: shareInfo.title, link: shareInfo.link, imgUrl: shareInfo.imgUrl, success: function () { onSuccess() }, cancel: function () { onCancel() }, }) wx.onMenuShareAppMessage({ title: shareInfo.title, desc: shareInfo.desc, link: shareInfo.link, imgUrl: shareInfo.imgUrl, type: 'link', success: function () { onSuccess() }, cancel: function () { onCancel() }, }) }
|
接下来,开始搭积木。因为考虑到分享这个操作,也是会在多个页面复用,那么有必要再抽象一个分享的方法,这样在需要用到微信分享的地方直接调用该方法就行。因此,笔者又新建了一个useWxShare.ts
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import { getJsSDKConfigApi } from "@/api/wechat"; import { useWxSDK } from "@/hooks/useWxSDK";
export function useWxShare(shareConfig: { title: string; imgUrl: string; desc: string; }) { const { initConfig, setShareInfo } = useWxSDK();
const shareUrl = window.location.href.split("#")[0];
getJsSDKConfigApi(shareUrl).then((config) => { initConfig(config).then(() => { setShareInfo({ ...shareConfig, link: shareUrl, }); }); }); }
|
至此,封装完毕,然后,咱们到页面组件到mounted函数里调用该方法,即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <script> import { useWxShare } from '@/hooks/useWxShare'
export default defineComponent({ setup() { }, mounted() { useWxShare({ title: '这是标题', desc: '这是描述', imgUrl: 'http://yourimg.com/share-pic.png', }) }, }) </script>
|
补坑
这样就结束了吗?当然不是,这里边有个大坑,笔者在之前的博客中也分享过,就是如果我们的页面是采用的Vue Router的history模式的路由的话,在某些情况下,会出现iOS设备上分享失效的问题。举个栗子。假设我们都通过http://domain.com
进入,然后跳转到路由为/share的页面需要用到jssdk,那么实际js-sdk进行签名校验时所获取的当前页面url在ios和andrioid是不同的,在安卓上没有任何问题,js-sdk校验的url就是当前页面的url,也就是http://domain.com/share
。而在iOS上,js-sdk校验的url是我们刚进入页面时候的url,也就是http://domain.com
,然而我们后端那边签名用的是当前页面的url,这就导致iOS上,签名校验不成功。
那么该如何处理呢?笔者这边采取的办法是在入口文件或者根组件中记录当前页面URL,在页面组件创建完成后,ios获取记录的url进行签名,android获取当前路由。所以填坑如下:
App.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import { defineComponent } from 'vue' import { useWxSDK } from '@/common/hooks/useWxSDK' import { commonStore } from '@/store/modules/common'
export default defineComponent({ name: 'App', setup() { const { isiOSWechat } = useWxSDK() if (isiOSWechat()) { const url = window.location.href.split('#')[0] commonStore.saveVisitUrl(url) } }, }) </script>
|
@/hooks/useWxSDK.ts
1 2 3 4
| function isiOSWechat() { return (window as any).__wxjs_is_wkwebview }
|
@/hooks/useWxShare.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import { getJsSDKConfigApi } from '@/api/wechat' import { useWxSDK } from '@/common/hooks/useWxSDK' import { commonStore } from '@/store/modules/common'
export function useWxShare(shareConfig: { title: string; imgUrl: string; desc: string }) { const { initConfig, setShareInfo, isiOSWechat } = useWxSDK()
const shareUrl = window.location.href.split('#')[0] const signatureUrl = isiOSWechat() ? commonStore.commonState.visitUrl : shareUrl
getJsSDKConfigApi(signatureUrl).then((config) => { initConfig(config).then(() => { setShareInfo({ ...shareConfig, link: shareUrl, }) }) }) }
|
@/store/modules/common.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import { Module, VuexModule, Mutation, getModule } from 'vuex-module-decorators' import store from '@/store' import { initialUnencryptedStorage } from '../globals'
interface CommonState { visitUrl: string }
const NAME = 'common'
@Module({ namespaced: true, name: NAME, dynamic: true, store, preserveState: Boolean(initialUnencryptedStorage[NAME]), }) export class Common extends VuexModule { commonState: CommonState = { visitUrl: '', }
@Mutation saveVisitUrl(url: string): void { this.commonState.visitUrl = url } }
export const commonStore = getModule<Common>(Common)
|
看效果
首先咱们还是使用微信开发工具上看看效果
先,输入咱项目的地址

打开后,可以看到,获取config信息的请求已成功发送和返回,再看控制台

控制台显示了wx.config的配置日志以及设置分享的日志,这个表示我们的分享配置成功了。点右上角分享,如果能显示我们配置的分享标题,那就没问题啦。

最后,还是要在真机上试试看,真机上分享出来后,效果如下:

需要体验的小伙伴,可以在微信中扫下边二维码

同时,笔者已经把项目的代码托管到了Github上,欢迎有需要的小伙伴点击该链接自取
总结
其实微信分享相对来说,功能并不复杂,难点在于如何妥当的处理JS-SDK在单页应用上的一些坑。另外,也就是代码组织和封装的问题了,笔者看过很多项目,在代码复用和抽象上没有多花心思,导致整个项目到处都是复制粘贴的重复代码,显得很臃肿。经过笔者这样解耦抽象后,在调用层只需要简单的一个函数即可,是不是就显得格外的优雅呢?
写在最后
最近工作稍微闲了些,笔者打算用Vue3+ts+vant从0开始完成一个公众号应用并将开发过程分享出来,也算是激励自己持续学习的一个方式吧。如果有想法和建议,欢迎找我探讨哦。
同时,为方便大家更好的探讨微信公众号开发相关技术,笔者也建了一个微信群,欢迎加入和大家一起学习成长。微信中扫下边二维码申请进群。
