uniapp多端分享实战指南(APP、小程序、公众号全覆盖)

一、引言

在移动互联网时代,分享功能几乎是所有应用必不可少的模块。用户希望将内容快速分享给朋友或朋友圈,企业也需要借助分享实现二次传播与推广。Uniapp 作为跨平台框架,能够同时打包成原生 APP、小程序以及 H5/公众号(Web)版本,但各端的分享实现方式大不相同:

  • 原生 APP(Android/iOS):使用 plus.share(或 plus.nativeUI)等原生 API,调用系统分享面板。
  • 微信/支付宝小程序:使用 uni.onShareAppMessageuni.updateShareMenuuni.showShareMenu,以及平台自带的分享配置接口。
  • 微信公众号(H5):通过微信 JS-SDKwx.config + wx.ready + wx.onMenuShareTimeline/wx.updateAppMessageShareData 等)来实现页面分享。

为了让「多端分享」的逻辑更清晰、可维护,我们需要设计一套统一的分享入口,根据运行环境(原生 APP、小程序、H5/公众号)自动调用相应的分享方法,同时支持动态更新分享内容(标题、描述、链接、缩略图等),并在用户分享后能够接收回调。

本文将以实战示例为主线,分以下几部分展开:

  1. 分享功能概览与流程
  2. 平台环境检测:如何在运行时判断当前是在 APP、小程序 还是 H5/公众号
  3. APP 端分享实战plus.share
  4. 小程序端分享实战uni.onShareAppMessage / uni.showShareMenu / uni.updateShareMenu…
  5. 公众号(H5)端分享实战(微信 JS-SDK 初始化与分享配置)
  6. 封装统一分享函数 + ASCII 图解
  7. 完整示例汇总
  8. 常见问题与注意事项

通过本篇指南,你可以在 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.shareuni.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 生效。

4.2 APP 端分享代码示例

4.2.1 配置分享参数

假设我们在页面中有一颗「分享按钮」,点击后弹出系统分享面板,并附带自定义参数。流程如下:

  1. 在页面的 script 中,根据需求准备分享数据(shareData)。
  2. 点击按钮后,调用 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-weixinmp-alipaymp-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 及以上才支持,返回值支持 titlequery(朋友圈打开时附带的 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 最新分享流程

  1. 后端接口获取签名参数

    • 在后端部署一个接口 /api/jssdk-config,接收当前页面 URL,调用微信开放平台的 access_tokenjsapi_ticket 接口,生成 nonceStrtimestampsignature,返回给前端。
  2. 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(兼容旧版)
  3. wx.ready() 中调用分享设置

    • wx.ready() 回调里,调用 wx.updateAppMessageShareData({...}) 设置「分享给好友」的参数;
    • 调用 wx.updateTimelineShareData({...}) 设置「分享到朋友圈」的参数;
  4. H5 页面:在渲染完成后,读取后端接口返回签名参数,并执行上述 wx.configwx.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}&timestamp=${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;

说明:

  • APPIDAPPSECRET 需要在环境变量或配置文件中定义;
  • 务必access_tokenjsapi_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 中至少要包含 updateAppMessageShareDataupdateTimelineShareData;如果要兼容低版本,也可以额外添加 onMenuShareAppMessageonMenuShareTimeline
  • 按钮点击后先调用 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' });
    }
  });
}

解释:

  1. APP 端:调用 uni.share({...}) 唤起系统分享。
  2. 小程序端:通过 uni.showShareMenu() + 用户点击右上角分享按钮;页面需实现 onShareAppMessage 并返回 shareConfig 中的小程序 pathtitleimageUrl 等;或者可在页面中动态调用 uni.updateShareAppMessage() 更新分享内容。
  3. H5/公众号端:先调用 wx.config(),待 wx.ready() 后调用 wx.updateAppMessageShareData()wx.updateTimelineShareData() 进行分享配置。成功后提示用户点击右上角分享。
  4. 其他环境:如非 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 示例

九、常见问题与注意事项

  1. 动态分享内容不生效

    • 小程序端:如果你在 onLoad 之后想动态修改分享内容,需调用 uni.updateShareMenu()uni.updateShareAppMessage(),否则 onShareAppMessage 中返回的内容不会更新。
    • H5 端:确保 wx.config 使用的 URL 与实际 location.href(去除 hash 后)一致,否则会报“签名校验失败”。
  2. 分享后回调不触发

    • 小程序:分享成功后只能拿到是否“分享成功”回调,部分平台(如支付宝小程序)在分享成功后不会回调 success,或需特定基础库版本支持。
    • APP:个别 Android 机型上,分享面板选择后没有回调,需要通过定时器去检测分享状态。
  3. 多端图片路径差异

    • APP 端 thumbs 支持相对路径(如 '_www/static/thumb.png')或远程 URL;
    • 小程序端 imageUrl 要求是远程 URL,或者必须先上传到腾讯云/阿里云等远程服务器;
    • H5 端直接使用绝对 URL 即可。
  4. 分享链接携带参数

    • 如果想对分享来源做统计,可在 shareConfig.link(H5/公众号)或 path(小程序)里添加 ?ref=xxx 参数,后端或小程序可根据此参数完成埋点。
  5. 安全性

    • H5 端不要把 postMessage 中带入的敏感数据直接插入到 DOM,避免 XSS;
    • 若需在 URL 上传 Token,建议先加密或签名,防止明文泄露;
  6. 不同平台的 API 差异

    • 虽然 Uniapp 为我们封装了跨平台调用,但在具体参数命名和可选字段上,各平台还是有差异。务必阅读《Uniapp 官方文档》中相关章节,以免版本更新导致接口行为变化。

十、总结

本文系统地介绍了如何在 Uniapp 项目中实现多端分享(APP、小程序、公众号全覆盖),包括:

  1. 平台环境检测:通过 #ifdef 与 UA 判断实现运行时分支;
  2. APP 端分享:调用 uni.share({ provider:'system', ... }),封装底层 plus.share
  3. 小程序端分享:在页面中实现 onShareAppMessageonShareTimeline,并可用 uni.showShareMenu()uni.updateShareMenu() 动态配置;
  4. 公众号 H5 端分享:使用微信 JS-SDK (wx.config + wx.ready + wx.updateAppMessageShareData / wx.updateTimelineShareData) 来动态设置分享;
  5. 统一分享函数 shareHandler():封装多端判断与调用逻辑,一处修改即可生效全平台;
  6. 完整示例代码:演示了项目目录结构、utils/platform.jsutils/share.js,以及首页与 WebView 页面的完整实现;
  7. 常见问题与注意事项:涵盖动态分享、签名校验、回调失效、图片路径、参数安全、多端 API 差异等。

通过“一次调用,多端适配”的思路,你可以让分享功能在各个平台下表现一致、可维护性高。

评论已关闭

推荐阅读

DDPG 模型解析,附Pytorch完整代码
2024年11月24日
DQN 模型解析,附Pytorch完整代码
2024年11月24日
AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日