uniapp多端分享实战指南(APP、小程序、公众号全覆盖)
一、引言
在移动互联网时代,分享功能几乎是所有应用必不可少的模块。用户希望将内容快速分享给朋友或朋友圈,企业也需要借助分享实现二次传播与推广。Uniapp 作为跨平台框架,能够同时打包成原生 APP、小程序以及 H5/公众号(Web)版本,但各端的分享实现方式大不相同:
- 原生 APP(Android/iOS):使用
plus.share
(或plus.nativeUI
)等原生 API,调用系统分享面板。 - 微信/支付宝小程序:使用
uni.onShareAppMessage
、uni.updateShareMenu
、uni.showShareMenu
,以及平台自带的分享配置接口。 - 微信公众号(H5):通过微信 JS-SDK(
wx.config
+wx.ready
+wx.onMenuShareTimeline
/wx.updateAppMessageShareData
等)来实现页面分享。
为了让「多端分享」的逻辑更清晰、可维护,我们需要设计一套统一的分享入口,根据运行环境(原生 APP、小程序、H5/公众号)自动调用相应的分享方法,同时支持动态更新分享内容(标题、描述、链接、缩略图等),并在用户分享后能够接收回调。
本文将以实战示例为主线,分以下几部分展开:
- 分享功能概览与流程
- 平台环境检测:如何在运行时判断当前是在 APP、小程序 还是 H5/公众号
- APP 端分享实战(
plus.share
) - 小程序端分享实战(
uni.onShareAppMessage
/uni.showShareMenu
/uni.updateShareMenu…
) - 公众号(H5)端分享实战(微信 JS-SDK 初始化与分享配置)
- 封装统一分享函数 + ASCII 图解
- 完整示例汇总
- 常见问题与注意事项
通过本篇指南,你可以在 Uniapp 项目中轻松实现「一次调用,多端生效」的分享方案,极大提升开发效率与维护性。
二、分享功能概览与流程
2.1 分享场景与目标
无论是内容分享、电商推广还是邀请好友,小程序/APP/H5 都需要提供分享入口,让用户能将当前页面或商品、活动海报等内容分享到微信好友、朋友圈、QQ、微博、系统短信、邮件等多种渠道。主要需求包括:
- 分享内容可自定义:标题(
title
)、描述(summary
)、链接(url
)、缩略图(thumb
)等都可以动态传入。 - 一键分享按钮:在页面显著位置放置「分享」按钮,点击后触发分享流程。
- 分享回调:在用户分享成功或取消时,能够捕获回调做埋点、统计或业务逻辑。
- 多端兼容:在原生 APP 端唤起系统分享面板,在小程序端/公众号端调用对应平台分享 API。
2.2 分享流程概览
以下用一个简单的 ASCII 流程图展示三端的分享流程,方便我们理解大致逻辑:
┌───────────────────────────────────────┐
│ 统一分享入口 │
│ (按钮点击 → 调用 shareHandler()) │
└───────────────────────────────────────┘
↓
┌──────────────┬──────────────┬──────────────┐
│ │ │ │
▼ ▼ ▼ ▼
【APP 端】 【微信小程序端】 【支付宝小程序端】 【H5/公众号端】
│ │ │ │
│ │ │ │
│ │ │ │
│ 用 plus.share │ uni.showShareMenu() │ wx.config() +
│ 调用系统分享 │ + uni.onShareAppMessage()│ wx.updateXXX() →
│ 面板(多平台)│ 或 uni.updateShareMenu() │ 调用微信 JS-SDK分享 │
│ │ │ │
└──────────────┴──────────────┴──────────────┘
- APP 端:通过
canIUse('plus.share')
判断是否在 APP 环境,调用plus.share.sendWithSystem({...})
或uni.share({...})
; - 小程序端:在页面
onLoad
/onShow
中调用uni.showShareMenu({ menus: ['shareAppMessage','shareTimeline'] })
,并在onShareAppMessage()
中返回分享配置;如果需要动态修改分享按钮或分享参数,可以调用uni.updateShareMenu()
或uni.updateShareAppMessage()
; - H5/公众号端:先通过后端取得微信 JS-SDK 签名参数,调用
wx.config({...})
,待wx.ready()
后使用wx.updateAppMessageShareData({...})
和wx.updateTimelineShareData({...})
设置分享内容; - 支付宝/百度等小程序:同微信小程序类似,API 名称不同,但调用流程一致,需要分别查看对应平台文档。
三、平台环境检测
为了在同一套代码里针对不同端调用不同分享逻辑,我们首先需要写一个平台检测函数,判断当前运行环境。Uniapp 在编译时会注入内置常量 process.env.PLATFORM
(HBuilderX)或通过 uni.getSystemInfoSync().platform
等。但更健壮的方式是结合 uni.getSystemInfo
与内置判断接口:
// utils/platform.js
export function getPlatform() {
// #ifdef APP-PLUS
return 'app-plus';
// #endif
// #ifdef MP-WEIXIN
return 'mp-weixin';
// #endif
// #ifdef MP-ALIPAY
return 'mp-alipay';
// #endif
// #ifdef MP-BAIDU
return 'mp-baidu';
// #endif
// #ifdef H5
// 可进一步通过用户代理判断是否在微信内置浏览器
const ua = navigator.userAgent.toLowerCase();
if (ua.indexOf('micromessenger') > -1) {
return 'h5-weixin';
} else if (ua.indexOf('alipay') > -1) {
return 'h5-alipay';
} else {
return 'h5-others';
}
// #endif
}
说明:
#ifdef APP-PLUS
、#ifdef MP-WEIXIN
等是 Uniapp 编译条件指令,只在对应端编译时生效;- H5 环境下,可借助
navigator.userAgent
判断是否在微信内置浏览器(h5-weixin
)、支付宝内置浏览器(h5-alipay
),或普通浏览器(h5-others
)。
在具体业务代码中,可以调用 const platform = getPlatform()
,并根据返回值来执行不同分享逻辑。
四、APP 端分享实战
4.1 plus.share
与 uni.share
简介
在原生 APP(通过 HBuilderX 发布的 Android/iOS 应用)中,可以使用 plus.share
(Plus API)来唤起系统分享面板。Uniapp 也封装了一层 uni.share
,可以在 APP 端直接调用。
plus.share.sendWithSystem({...})
:- 允许传递分享标题、摘要、链接、缩略图、媒体类型等参数;
- 底层会调用系统分享(iOS/Android 原生)弹窗,列出微信、QQ、微博、蓝牙、短信、邮件等可分享渠道。
- 成功回调与失败回调都可以捕获。
uni.share
:- 在 APP 端会被映射为
plus.share.sendWithSystem
; - 在其他端(小程序/H5)无效,仅在 APP-PLUS 生效。
- 在 APP 端会被映射为
4.2 APP 端分享代码示例
4.2.1 配置分享参数
假设我们在页面中有一颗「分享按钮」,点击后弹出系统分享面板,并附带自定义参数。流程如下:
- 在页面的
script
中,根据需求准备分享数据(shareData
)。 - 点击按钮后,调用
uni.share(shareData)
。
<template>
<view class="container">
<button @click="onShareApp">在 APP 中分享</button>
</view>
</template>
<script>
import { getPlatform } from '@/utils/platform';
export default {
data() {
return {
shareData: {
provider: 'system', // 使用系统分享
title: 'Uniapp 多端分享指南', // 分享标题
summary: '一键覆盖 APP、小程序、公众号的分享实战方案', // 分享摘要
href: 'https://example.com/download', // 分享链接(可选)
thumbs: ['_www/icons/share-thumb.png'], // 缩略图路径(相对路径或远程 URL)
miniProgram: {
// 如果分享到微信,可以指定小程序路径
id: 'gh_abcdefg', // 小程序原始 ID
path: '/pages/index/index',
type: 0 // 0: 正常小程序,1: 体验版,2: 开发版
}
}
};
},
methods: {
onShareApp() {
const platform = getPlatform();
if (platform !== 'app-plus') {
uni.showToast({ title: '只在 APP 环境生效', icon: 'none' });
return;
}
// 优先设置默认分享内容,也可以在此处动态修改 shareData
uni.share({
provider: 'system',
title: this.shareData.title,
summary: this.shareData.summary,
href: this.shareData.href,
thumbs: this.shareData.thumbs,
miniProgram: this.shareData.miniProgram,
success: (res) => {
uni.showToast({ title: '分享成功', icon: 'success' });
console.log('分享成功:', res);
},
fail: (err) => {
uni.showToast({ title: '分享失败', icon: 'none' });
console.error('分享失败:', err);
}
});
}
}
};
</script>
<style>
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
button {
padding: 10px 20px;
font-size: 16px;
}
</style>
说明:
provider: 'system'
表示调用系统分享面板;如果想指定分享到某个应用(如微信好友、QQ 等),可以改为provider: 'weixin'
、'qq'
。thumbs
可以是相对 HBuilderX 项目www
目录的路径,也可以使用远程 URL。miniProgram
对象只有分享到“微信朋友圈/微信好友”时才有效,用于指定要分享的小程序信息;其他渠道会忽略此项。- 如果想在分享成功后做埋点,可以在
success
回调里进行统计上报。
4.3 APP 端分享逻辑图解
┌───────────────────────────────────────────┐
│ 用户点击 “APP 中分享” 按钮 │
└───────────────────────────────────────────┘
↓
┌───────────────────────────────────────────┐
│ 调用 uni.share({ provider:'system', │
│ title, summary, href, thumbs, │
│ miniProgram }) │
└───────────────────────────────────────────┘
↓
┌───────────────────────────────────────────┐
│ 底层执行 plus.share.sendWithSystem({...}) │
│ └───────────────────────────────────────┘ │
└───────────────────────────────────────────┘
↓
┌───────────────────────────────────────────┐
│ 系统分享面板出现(列举微信、QQ、微博等) │
└───────────────────────────────────────────┘
↓
┌───────────────────────────────────────────┐
│ 用户选择分享渠道并确认分享 → 系统完成分享 │
└───────────────────────────────────────────┘
↓
┌───────────────────────────────────────────┐
│ 成功/失败 回调 → 执行 success/fail │
└───────────────────────────────────────────┘
五、小程序端分享实战
在 Uniapp 编译为各类小程序(mp-weixin
、mp-alipay
、mp-baidu
)后,小程序端的分享流程与普通原生小程序开发类似,需要在页面内调用对应分享 API。
5.1 微信小程序端分享
5.1.1 页面 onShareAppMessage
配置
在微信小程序端,只要在页面的 script
中定义 onShareAppMessage
(分享给好友)或 onShareTimeline
(分享朋友圈)函数,返回一个「分享配置对象」,小程序就会在右上角显示“分享”按钮,并在用户点击后自动触发此函数获取分享内容。
<template>
<view class="page">
<text>这是一个微信小程序分享示例页面</text>
<!-- 如果想手动触发分享,也可用 <button open-type="share">触发分享</button> -->
</view>
</template>
<script>
export default {
data() {
return {
shareTitle: 'Uniapp 多端分享指南(微信小程序)',
sharePath: '/pages/webview/webview?ref=wechat',
shareImageUrl: 'https://example.com/share-thumb.png'
};
},
// 分享给好友
onShareAppMessage() {
return {
title: this.shareTitle,
path: this.sharePath, // 分享后打开的小程序路径
imageUrl: this.shareImageUrl, // 自定义分享缩略图(尺寸 300×200px 建议)
success: () => {
uni.showToast({ title: '分享成功', icon: 'success' });
},
fail: () => {
uni.showToast({ title: '分享失败', icon: 'none' });
}
};
},
// 分享朋友圈(仅在 2.7.0+ 基础库可用)
onShareTimeline() {
return {
title: this.shareTitle,
query: 'ref=timeline', // 分享到朋友圈时传递的参数
imageUrl: this.shareImageUrl // 可选:朋友圈缩略图
};
},
onLoad() {
// 如果需要动态更新分享内容,可在 onLoad 或其他逻辑中调用 uni.updateShareMenu
uni.showShareMenu({
withShareTicket: true, // 如果需要获取更多分享后的信息
menus: ['shareAppMessage','shareTimeline']
});
}
};
</script>
<style>
.page {
padding: 20px;
}
</style>
说明:
onShareAppMessage
返回值支持配置分享标题(title
)、分享路径(path
,可附带 query 参数)、缩略图(imageUrl
)等;onShareTimeline
仅在微信基础库 2.7.0 及以上才支持,返回值支持title
、query
(朋友圈打开时附带的 query)和imageUrl
;如果需要在页面任意时机动态修改分享内容(而不是依赖用户点击右上角菜单触发),可以在
onLoad
或业务方法中调用:uni.updateShareMenu({ withShareTicket: true, menus: ['shareAppMessage','shareTimeline'] }); uni.updateShareAppMessage({ title: '新的标题', path: '/pages/index/index?from=update', imageUrl: 'https://example.com/new-thumb.png' });
uni.showShareMenu()
与uni.updateShareMenu()
可以控制哪些分享入口展示,以及是否获取分享信息(shareTicket
)。
5.1.2 小程序端分享流程图解
┌───────────────────────────────────────┐
│ 用户点击右上角“...”按钮 │
└───────────────────────────────────────┘
↓
┌───────────────────────────────────────┐
│ 小程序调用 onShareAppMessage │
│ ↓ 返回分享配置(title、path) │
└───────────────────────────────────────┘
↓
┌───────────────────────────────────────┐
│ 用户选择“发送给微信好友/分享到朋友圈” │
└───────────────────────────────────────┘
↓
┌───────────────────────────────────────┐
│ 分享成功/失败 回调(success/fail) │
└───────────────────────────────────────┘
5.2 支付宝 & 百度小程序端分享
与微信小程序类似,支付宝小程序和百度小程序也提供相应的分享 API,接口命名略有不同,但思路一致。
5.2.1 支付宝小程序分享
onShareAppMessage
:返回分享给好友的配置。onShareApp
:支付宝基础库 10.1.72+ 支持分享卡片到支付宝好友、生活号等。
<template>
<view class="page">
<text>这是一个支付宝小程序分享示例页面</text>
</view>
</template>
<script>
export default {
data() {
return {
shareTitle: 'Uniapp 多端分享指南(支付宝小程序)',
shareDesc: '覆盖 APP、小程序、公众号的分享实战方案',
sharePath: '/pages/index/index?ref=alipay',
shareImageUrl: 'https://example.com/ali-thumb.png'
};
},
onShareAppMessage() {
return {
title: this.shareTitle,
desc: this.shareDesc,
path: this.sharePath,
imageUrl: this.shareImageUrl,
success: () => {
my.showToast({ content: '分享成功' });
},
fail: () => {
my.showToast({ content: '分享失败' });
}
};
},
onShareApp() {
// 支付宝 10.1.72+ 支持:分享 App 到生活号、工作消息
return {
title: this.shareTitle,
desc: this.shareDesc,
path: this.sharePath,
imageUrl: this.shareImageUrl
};
}
};
</script>
<style>
.page {
padding: 20px;
}
</style>
5.2.2 百度小程序分享
百度小程序的 API 与微信相似(但高低版本差异较大,以下示例适用于 3.3200+ 基础库):
<template>
<view class="page">
<text>这是一个百度小程序分享示例页面</text>
</view>
</template>
<script>
export default {
data() {
return {
shareTitle: 'Uniapp 多端分享指南(百度小程序)',
sharePath: '/pages/index/index?ref=baidu',
shareImageUrl: 'https://example.com/baidu-thumb.png'
};
},
onShareAppMessage() {
return {
title: this.shareTitle,
path: this.sharePath,
imageUrl: this.shareImageUrl
};
},
onShareTimeline() {
return {
title: this.shareTitle,
query: 'ref=timeline',
imageUrl: this.shareImageUrl
};
}
};
</script>
<style>
.page {
padding: 20px;
}
</style>
注意:
- 各平台基础库版本可能会影响分享接口命名与参数,请务必在官方文档中确认你所使用的基础库版本支持的 API。
onShareTimeline
在百度小程序中有时需要在manifest.json
中开启“分享到朋友圈”功能。
六、公众号(H5)端分享实战
对于 H5/公众号环境,分享并非 Uniapp 底层封装,而需要使用后端配合的微信 JS-SDK(或支付宝 JSSDK)来配置页面分享。
6.1 微信 JS-SDK 最新分享流程
后端接口获取签名参数
- 在后端部署一个接口
/api/jssdk-config
,接收当前页面 URL,调用微信开放平台的access_token
和jsapi_ticket
接口,生成nonceStr
、timestamp
、signature
,返回给前端。
- 在后端部署一个接口
H5 页面引用并调用
wx.config({...})
- H5 在页面
<head>
中引入https://res.wx.qq.com/open/js/jweixin-1.6.0.js
; 在
wx.config({ debug:false, appId, timestamp, nonceStr, signature, jsApiList: [...] })
中列出要调用的分享接口:updateAppMessageShareData
(新版分享给好友)updateTimelineShareData
(新版分享到朋友圈)onMenuShareAppMessage
/onMenuShareTimeline
(兼容旧版)
- H5 在页面
wx.ready()
中调用分享设置- 在
wx.ready()
回调里,调用wx.updateAppMessageShareData({...})
设置「分享给好友」的参数; - 调用
wx.updateTimelineShareData({...})
设置「分享到朋友圈」的参数;
- 在
- H5 页面:在渲染完成后,读取后端接口返回签名参数,并执行上述
wx.config
和wx.ready
逻辑。
6.1.1 后端示例(Node.js 伪代码)
// backend/routes/wechatJssdk.js
const express = require('express');
const router = express.Router();
const axios = require('axios');
const crypto = require('crypto');
// 1. 获取 access_token
async function getAccessToken() {
// 这里需缓存 access_token(有效期 2h),避免频繁请求
const res = await axios.get(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`);
return res.data.access_token;
}
// 2. 获取 jsapi_ticket
async function getJsApiTicket(accessToken) {
// 同样需缓存 ticket(有效期 2h)
const res = await axios.get(`https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${accessToken}&type=jsapi`);
return res.data.ticket;
}
// 3. 生成签名
function createSignature(ticket, url) {
const nonceStr = crypto.randomBytes(16).toString('hex');
const timestamp = Math.floor(Date.now() / 1000);
const str = `jsapi_ticket=${ticket}&noncestr=${nonceStr}×tamp=${timestamp}&url=${url}`;
const signature = crypto.createHash('sha1').update(str).digest('hex');
return { nonceStr, timestamp, signature };
}
// 4. 接口:前端传递当前页面 URL,返回签名参数
router.get('/jssdk-config', async (req, res) => {
const url = decodeURIComponent(req.query.url);
try {
const accessToken = await getAccessToken();
const ticket = await getJsApiTicket(accessToken);
const { nonceStr, timestamp, signature } = createSignature(ticket, url);
res.json({
appId: APPID,
timestamp,
nonceStr,
signature
});
} catch (err) {
console.error(err);
res.status(500).json({ error: '获取 JSSDK 配置失败' });
}
});
module.exports = router;
说明:
APPID
、APPSECRET
需要在环境变量或配置文件中定义;- 务必将
access_token
、jsapi_ticket
缓存(如 Redis、内存)并定时刷新,防止频繁请求微信接口;- 前端请求该接口时,URL 必须与实际浏览器地址保持一致(包含 protocol、域名、路径、query),否则签名校验会失败。
6.1.2 H5 页面实现分享
下面演示一个典型的公众号分享示例,假设页面 URL 为 https://example.com/h5/share.html
:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>公众号 H5 分享示例</title>
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
</head>
<body>
<h1>欢迎使用 Uniapp 多端分享示例(H5/公众号)</h1>
<button id="shareBtn">分享给好友 / 朋友圈</button>
<script>
// 在页面加载时获取签名等参数
async function initWeixinShare() {
const pageUrl = encodeURIComponent(location.href.split('#')[0]);
try {
const res = await fetch(`https://api.yourserver.com/jssdk-config?url=${pageUrl}`);
const data = await res.json();
wx.config({
debug: false,
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: [
'updateAppMessageShareData',
'updateTimelineShareData',
'onMenuShareAppMessage',
'onMenuShareTimeline'
]
});
} catch (e) {
console.error('获取微信 JSSDK 配置失败', e);
}
}
// 设置分享参数
function setupShare(shareConfig) {
// 新版分享给好友
wx.updateAppMessageShareData({
title: shareConfig.title, // 分享标题
desc: shareConfig.desc, // 分享描述
link: shareConfig.link, // 分享链接,该链接域名需与 sign 时传的 URL 保持一致
imgUrl: shareConfig.imgUrl, // 分享缩略图
success: () => {
alert('分享给好友 设置成功');
},
fail: (err) => {
console.error('分享好友设置失败', err);
}
});
// 新版分享到朋友圈
wx.updateTimelineShareData({
title: shareConfig.title, // 分享标题(朋友圈只显示标题)
link: shareConfig.link,
imgUrl: shareConfig.imgUrl,
success: () => {
alert('分享到朋友圈 设置成功');
},
fail: (err) => {
console.error('分享朋友圈设置失败', err);
}
});
// 兼容旧版回调(可选)
wx.onMenuShareAppMessage({
title: shareConfig.title,
desc: shareConfig.desc,
link: shareConfig.link,
imgUrl: shareConfig.imgUrl,
success: () => {},
cancel: () => {}
});
wx.onMenuShareTimeline({
title: shareConfig.title,
link: shareConfig.link,
imgUrl: shareConfig.imgUrl,
success: () => {},
cancel: () => {}
});
}
document.addEventListener('DOMContentLoaded', () => {
initWeixinShare();
document.getElementById('shareBtn').addEventListener('click', () => {
// 动态读取或构造分享配置
const shareConfig = {
title: 'Uniapp 多端分享指南(公众号 H5)',
desc: '覆盖 APP、小程序、公众号的分享实战方案',
link: location.href,
imgUrl: 'https://example.com/ws-thumb.png'
};
setupShare(shareConfig);
alert('请点击右上角“...”选择“分享到朋友圈”或“分享给朋友”');
});
});
wx.ready(() => {
console.log('微信 JSSDK 已就绪');
});
wx.error((err) => {
console.error('微信 JSSDK Error: ', err);
});
</script>
</body>
</html>
说明:
location.href.split('#')[0]
用于去除可能带有#
的 hash 部分,确保签名 URL 与实际页面一致;jsApiList
中至少要包含updateAppMessageShareData
和updateTimelineShareData
;如果要兼容低版本,也可以额外添加onMenuShareAppMessage
和onMenuShareTimeline
;- 按钮点击后先调用
setupShare()
配置分享参数,然后提示用户点击右上角“...”进行分享;你也可以不显示按钮,直接在wx.ready()
时就自动调用setupShare()
,让分享入口即时生效;- 如果在页面加载时就要自动配置分享,可把
setupShare()
放进wx.ready()
回调中,不依赖按钮触发。
七、封装统一分享函数
为避免在每个页面中都写一堆平台判断和分享逻辑,我们可以封装一个统一分享接口,在业务层只需调用 shareHandler(shareConfig)
即可。示例如下:
// utils/share.js
import { getPlatform } from './platform';
// shareConfig 示例:
/*
{
title: '分享标题',
desc: '分享描述',
link: '分享链接(H5/APP/小程序通用)',
imgUrl: '分享缩略图',
path: '/pages/index/index?ref=mini', // 小程序分享 path
miniProgram: {
id: 'gh_abcdefg',
path: '/pages/index/index',
type: 0
}
}
*/
export async function shareHandler(shareConfig) {
const platform = getPlatform();
// 一、APP 端
if (platform === 'app-plus') {
// 调用 plus 分享
uni.share({
provider: 'system',
title: shareConfig.title,
summary: shareConfig.desc,
href: shareConfig.link,
thumbs: [shareConfig.imgUrl],
miniProgram: shareConfig.miniProgram || {},
success: () => {
uni.showToast({ title: '分享成功', icon: 'success' });
},
fail: (err) => {
console.error('APP 分享失败:', err);
uni.showToast({ title: '分享失败', icon: 'none' });
}
});
return;
}
// 二、小程序端
if (platform.startsWith('mp-')) {
// 只需先调用 uni.showShareMenu 启用分享按钮,然后设置分享内容
uni.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage','shareTimeline']
});
// 动态更新分享
uni.updateShareMenu({
withShareTicket: true,
menus: ['shareAppMessage','shareTimeline']
});
// 返回 shareConfig 中小程序路径;具体分享回调需要在页面中实现 onShareAppMessage
uni.showToast({ title: '请点击右上角“分享”', icon: 'none' });
return;
}
// 三、H5/公众号端
if (platform.startsWith('h5')) {
// 先获取 JSSDK 签名参数
const pageUrl = encodeURIComponent(location.href.split('#')[0]);
try {
const res = await fetch(`https://api.yourserver.com/jssdk-config?url=${pageUrl}`);
const data = await res.json();
wx.config({
debug: false,
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: [
'updateAppMessageShareData',
'updateTimelineShareData',
'onMenuShareAppMessage',
'onMenuShareTimeline'
]
});
wx.ready(() => {
// 配置最新分享内容
wx.updateAppMessageShareData({
title: shareConfig.title,
desc: shareConfig.desc,
link: shareConfig.link,
imgUrl: shareConfig.imgUrl
});
wx.updateTimelineShareData({
title: shareConfig.title,
link: shareConfig.link,
imgUrl: shareConfig.imgUrl
});
uni.showToast({ title: '分享配置已更新', icon: 'none' });
});
wx.error((err) => {
console.error('微信 JSSDK 配置失败:', err);
});
} catch (e) {
console.error('获取 JSSDK 配置失败:', e);
}
return;
}
// 四、hybird 其他情况:直接复制链接
uni.setClipboardData({
data: shareConfig.link,
success: () => {
uni.showToast({ title: '已复制链接,请手动分享', icon: 'none' });
}
});
}
解释:
- APP 端:调用
uni.share({...})
唤起系统分享。- 小程序端:通过
uni.showShareMenu()
+ 用户点击右上角分享按钮;页面需实现onShareAppMessage
并返回shareConfig
中的小程序path
、title
、imageUrl
等;或者可在页面中动态调用uni.updateShareAppMessage()
更新分享内容。- H5/公众号端:先调用
wx.config()
,待wx.ready()
后调用wx.updateAppMessageShareData()
和wx.updateTimelineShareData()
进行分享配置。成功后提示用户点击右上角分享。- 其他环境:如非 APP、非小程序、非公众号内浏览器,可选择将链接复制到剪贴板,提示用户手动粘贴分享。
7.1 ASCII 图解:统一分享流程
┌────────────────────────────────────────────────────┐
│ shareHandler(shareConfig) │
└────────────────────────────────────────────────────┘
↓
┌──────────────┬──────────────┬──────────────┬──────────────┐
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
【APP-PLUS】 【mp-weixin】 【mp-alipay】 【h5-weixin】 【其他环境】
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
│ uni.showShareMenu() │ │ │
│ + user点击菜单触发 │ │ │
│ onShareAppMessage() │ │ │
│ │ │ │ │
│ uni.share({...}) │ │ │ │
│ │ │ │ │
│ 唤起系统分享面板 │ │ │ │
│ │ │ │ │
│ │ │ wx.config() → wx.ready() │
│ │ │ → wx.updateAppMessage… │
│ │ │ → 提示点击右上角“分享” │
│ │ │ │ │
│ │ │ │ clipboardData │
└──────────────┴──────────────┴──────────────┴──────────────┘
八、完整示例汇总
下面给出一个完整的 Uniapp 项目示例,整合上述各端的分享逻辑。可以直接复制到你的 Uniapp 项目中,进行微调后投入使用。
8.1 项目目录结构
uni-share-demo/
├─ components/ # 可放置公共组件,如果有需要
├─ pages/
│ ├─ index/ # 主页,包含分享入口
│ │ ├─ index.vue
│ │ └─ index.js
│ └─ webview/ # H5 测试页面入口
│ ├─ webview.vue
│ └─ webview.js
├─ static/ # 存放缩略图等静态资源
│ └─ thumb.png
├─ utils/
│ ├─ platform.js
│ └─ share.js
├─ App.vue
├─ main.js
├─ manifest.json
└─ pages.json
8.2 utils/platform.js
export function getPlatform() {
// #ifdef APP-PLUS
return 'app-plus';
// #endif
// #ifdef MP-WEIXIN
return 'mp-weixin';
// #endif
// #ifdef MP-ALIPAY
return 'mp-alipay';
// #endif
// #ifdef MP-BAIDU
return 'mp-baidu';
// #endif
// #ifdef H5
const ua = navigator.userAgent.toLowerCase();
if (ua.indexOf('micromessenger') > -1) {
return 'h5-weixin';
} else if (ua.indexOf('alipay') > -1) {
return 'h5-alipay';
} else {
return 'h5-others';
}
// #endif
}
8.3 utils/share.js
import { getPlatform } from './platform';
export async function shareHandler(shareConfig) {
const platform = getPlatform();
// 一、APP 端
if (platform === 'app-plus') {
uni.share({
provider: 'system',
title: shareConfig.title,
summary: shareConfig.desc,
href: shareConfig.link,
thumbs: [shareConfig.imgUrl],
miniProgram: shareConfig.miniProgram || {},
success: () => {
uni.showToast({ title: '分享成功', icon: 'success' });
},
fail: (err) => {
console.error('APP 分享失败:', err);
uni.showToast({ title: '分享失败', icon: 'none' });
}
});
return;
}
// 二、小程序端
if (platform.startsWith('mp-')) {
// 显示分享按钮
uni.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage','shareTimeline']
});
uni.updateShareMenu({
withShareTicket: true,
menus: ['shareAppMessage','shareTimeline']
});
uni.showToast({ title: '请点击右上角“分享”', icon: 'none' });
return;
}
// 三、H5/公众号端
if (platform.startsWith('h5')) {
const pageUrl = encodeURIComponent(location.href.split('#')[0]);
try {
const res = await fetch(`https://api.yourserver.com/jssdk-config?url=${pageUrl}`);
const data = await res.json();
wx.config({
debug: false,
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: [
'updateAppMessageShareData',
'updateTimelineShareData',
'onMenuShareAppMessage',
'onMenuShareTimeline'
]
});
wx.ready(() => {
wx.updateAppMessageShareData({
title: shareConfig.title,
desc: shareConfig.desc,
link: shareConfig.link,
imgUrl: shareConfig.imgUrl
});
wx.updateTimelineShareData({
title: shareConfig.title,
link: shareConfig.link,
imgUrl: shareConfig.imgUrl
});
uni.showToast({ title: '分享配置已更新', icon: 'none' });
});
wx.error((err) => {
console.error('微信 JSSDK 配置失败:', err);
});
} catch (e) {
console.error('获取 JSSDK 配置失败:', e);
}
return;
}
// 四、其他环境
uni.setClipboardData({
data: shareConfig.link,
success: () => {
uni.showToast({ title: '已复制链接,请手动分享', icon: 'none' });
}
});
}
8.4 pages/index/index.vue
<template>
<view class="container">
<text>Uniapp 多端分享实战示例</text>
<button @click="onShare">分享全平台</button>
</view>
</template>
<script>
import { shareHandler } from '@/utils/share';
export default {
data() {
return {
shareConfig: {
title: 'Uniapp 多端分享指南',
desc: '覆盖 APP、小程序、公众号的分享实战方案',
link: 'https://example.com/h5/share.html',
imgUrl: 'https://example.com/static/thumb.png',
path: '/pages/index/index?from=mini',
miniProgram: {
id: 'gh_abcdefg',
path: '/pages/index/index',
type: 0
}
}
};
},
methods: {
async onShare() {
await shareHandler(this.shareConfig);
}
}
};
</script>
<style>
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
button {
margin-top: 20px;
padding: 10px 20px;
}
</style>
说明:
shareConfig.link
用于 H5/公众号端分享链接,也可作 APP 端分享的下载链接;shareConfig.path
用于小程序端分享路径,必须以/pages/...
开头;miniProgram
对象用于 APP 端分享到微信时,显示小程序卡片;shareHandler
内部会根据运行环境调用相应分享逻辑。
8.5 pages/webview/webview.vue
<template>
<view class="container">
<web-view
id="myWebview"
src="{{url}}"
bindload="onWebviewLoad"
bindmessage="onWebMessage"
/>
</view>
</template>
<script>
import { getPlatform } from '@/utils/platform';
export default {
data() {
return {
url: '' // 外部传入 H5 地址
};
},
onLoad(options) {
this.url = decodeURIComponent(options.src || '');
this.webviewCtx = null;
},
onReady() {
const platform = getPlatform();
if (platform === 'app-plus') {
// APP 端直接调用 shareHandler
// 但在 WebView 中分享逻辑通常不在这里处理
} else {
// 小程序/H5 端创建 WebViewContext
this.webviewCtx = uni.createWebViewContext('myWebview');
}
},
onWebviewLoad() {
// 当 H5 页面加载完成后,如果需要小程序主动推送数据给 H5,可在此调用:
const platform = getPlatform();
if (platform.startsWith('mp-') || platform.startsWith('h5')) {
const initMsg = { command: 'init', payload: { userId: 10086, token: 'abc123' } };
this.webviewCtx.postMessage({ data: initMsg });
}
},
onWebMessage(e) {
const msg = e.detail.data || {};
console.log('收到 H5 消息:', msg);
if (msg.command === 'h5ToMini') {
uni.showToast({ title: `H5 说:${msg.payload.text}`, icon: 'none' });
} else if (msg.command === 'paymentDone') {
uni.showToast({ title: `订单 ${msg.payload.orderId} 支付成功`, icon: 'success' });
uni.navigateBack();
}
}
};
</script>
<style>
.container {
width: 100%;
height: 100vh;
}
</style>
H5 页面配合示例
https://example.com/h5/share.html
:公众号 H5 分享https://example.com/h5/h5-to-mini.html
:H5 → 小程序 postMessage 示例
九、常见问题与注意事项
动态分享内容不生效
- 小程序端:如果你在
onLoad
之后想动态修改分享内容,需调用uni.updateShareMenu()
与uni.updateShareAppMessage()
,否则onShareAppMessage
中返回的内容不会更新。 - H5 端:确保
wx.config
使用的 URL 与实际location.href
(去除 hash 后)一致,否则会报“签名校验失败”。
- 小程序端:如果你在
分享后回调不触发
- 小程序:分享成功后只能拿到是否“分享成功”回调,部分平台(如支付宝小程序)在分享成功后不会回调
success
,或需特定基础库版本支持。 - APP:个别 Android 机型上,分享面板选择后没有回调,需要通过定时器去检测分享状态。
- 小程序:分享成功后只能拿到是否“分享成功”回调,部分平台(如支付宝小程序)在分享成功后不会回调
多端图片路径差异
- APP 端
thumbs
支持相对路径(如'_www/static/thumb.png'
)或远程 URL; - 小程序端
imageUrl
要求是远程 URL,或者必须先上传到腾讯云/阿里云等远程服务器; - H5 端直接使用绝对 URL 即可。
- APP 端
分享链接携带参数
- 如果想对分享来源做统计,可在
shareConfig.link
(H5/公众号)或path
(小程序)里添加?ref=xxx
参数,后端或小程序可根据此参数完成埋点。
- 如果想对分享来源做统计,可在
安全性
- H5 端不要把
postMessage
中带入的敏感数据直接插入到 DOM,避免 XSS; - 若需在 URL 上传 Token,建议先加密或签名,防止明文泄露;
- H5 端不要把
不同平台的 API 差异
- 虽然 Uniapp 为我们封装了跨平台调用,但在具体参数命名和可选字段上,各平台还是有差异。务必阅读《Uniapp 官方文档》中相关章节,以免版本更新导致接口行为变化。
十、总结
本文系统地介绍了如何在 Uniapp 项目中实现多端分享(APP、小程序、公众号全覆盖),包括:
- 平台环境检测:通过
#ifdef
与 UA 判断实现运行时分支; - APP 端分享:调用
uni.share({ provider:'system', ... })
,封装底层plus.share
; - 小程序端分享:在页面中实现
onShareAppMessage
、onShareTimeline
,并可用uni.showShareMenu()
、uni.updateShareMenu()
动态配置; - 公众号 H5 端分享:使用微信 JS-SDK (
wx.config
+wx.ready
+wx.updateAppMessageShareData
/wx.updateTimelineShareData
) 来动态设置分享; - 统一分享函数
shareHandler()
:封装多端判断与调用逻辑,一处修改即可生效全平台; - 完整示例代码:演示了项目目录结构、
utils/platform.js
、utils/share.js
,以及首页与 WebView 页面的完整实现; - 常见问题与注意事项:涵盖动态分享、签名校验、回调失效、图片路径、参数安全、多端 API 差异等。
通过“一次调用,多端适配”的思路,你可以让分享功能在各个平台下表现一致、可维护性高。
评论已关闭