Vue微信开发中微信分享的优雅实现

前言 微信分享主要是可以把我们做的网页分享给好友或者分享到朋友圈,在发送给好友时,展示出来的消息不是一段很丑的网址,而是带着图文描述的特殊模板消息,很多传播性质比较强的网页都会借助这个特性提升传播性。要实现这个功能,需要我们接入微信的JS-SDK,JS-SDK是什么呢?官方文档介绍如下:

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

笔者这里安装的是ts版本, 安装完后,package.json中显示了安装的版本
Vue微信开发中微信分享的优雅实现
文章图片

封装模块
本着功能解耦原则和方便复用,笔者决定单独新建一个文件,专门封装js-sdk相关的功能。在vue3中,当然是封装成hook啦。所以,咱们在hooks目录下,新建了一个useWxSDK.ts文件;
然后,开始封装第一个方法,即wx.config
/** * 初始化设置 */ 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语法来实现配置成功后的操作啦!
接下来封装分享好友和微信朋友圈的方法:
/** 设置微信分享 */ function setShareInfo(shareInfo,onSuccess, onCancel) { wx.onMenuShareTimeline({ title: shareInfo.title, // 分享标题 link: shareInfo.link, // 分享链接,可以不是当前页面,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 imgUrl: shareInfo.imgUrl, success: function () { // 用户确认分享后执行的回调函数 onSuccess() }, cancel: function () { onCancel() // 用户取消分享后执行的回调函数 }, }) wx.onMenuShareAppMessage({ title: shareInfo.title, // 分享标题 desc: shareInfo.desc, link: shareInfo.link, // 分享链接,可以不是当前页面,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 imgUrl: shareInfo.imgUrl, type: 'link', // 分享类型,music、video或link,不填默认为link success: function () { // 用户确认分享后执行的回调函数 onSuccess() }, cancel: function () { // 用户取消分享后执行的回调函数 onCancel() }, }) }

接下来,开始搭积木。因为考虑到分享这个操作,也是会在多个页面复用,那么有必要再抽象一个分享的方法,这样在需要用到微信分享的地方直接调用该方法就行。因此,笔者又新建了一个useWxShare.ts文件
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) => { // 调用后端接口获取config相关信息 initConfig(config).then(() => { // 注入wx.config成功后,设置微信分享相关 setShareInfo({ ...shareConfig, link: shareUrl, }); }); }); }

至此,封装完毕,然后,咱们到页面组件到mounted函数里调用该方法,即可

补坑
这样就结束了吗?当然不是,这里边有个大坑,笔者在之前的博客中也分享过,就是如果我们的页面是采用的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
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() // 检测到是ios微信,则把入口页地址记录到store中 if (isiOSWechat()) { const url = window.location.href.split('#')[0] commonStore.saveVisitUrl(url) } }, })

@/hooks/useWxSDK.ts
/** 是否是ios微信 */ function isiOSWechat() { return (window as any).__wxjs_is_wkwebview }

@/hooks/useWxShare.ts
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] // 对签名url做特殊判断处理 const signatureUrl = isiOSWechat() ? commonStore.commonState.visitUrl : shareUrlgetJsSDKConfigApi(signatureUrl).then((config) => { initConfig(config).then(() => { setShareInfo({ ...shareConfig, link: shareUrl, }) }) }) }

@/store/modules/common.ts
import { Module, VuexModule, Mutation, getModule } from 'vuex-module-decorators' import store from '@/store' import { initialUnencryptedStorage } from '../globals'interface CommonState { /** ios微信用,记录访问时候页面url */ 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)

看效果 首先咱们还是使用微信开发工具上看看效果
先,输入咱项目的地址
Vue微信开发中微信分享的优雅实现
文章图片

打开后,可以看到,获取config信息的请求已成功发送和返回,再看控制台
Vue微信开发中微信分享的优雅实现
文章图片

控制台显示了wx.config的配置日志以及设置分享的日志,这个表示我们的分享配置成功了。点右上角分享,如果能显示我们配置的分享标题,那就没问题啦。
Vue微信开发中微信分享的优雅实现
文章图片

最后,还是要在真机上试试看,真机上分享出来后,效果如下:
Vue微信开发中微信分享的优雅实现
文章图片

需要体验的小伙伴,可以在微信中扫下边二维码
Vue微信开发中微信分享的优雅实现
文章图片

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

    推荐阅读