用户在手机上想把这页分享出去,你那一排微信微博按钮其实一个都点不对——浏览器早就自带系统分享面板了

先说结论:移动端分享这件事,你不需要再堆一排第三方社交按钮,也不需要引任何 SDK。浏览器里就有 navigator.share(),一行调用直接唤起系统原生的分享面板——iOS 的分享 Sheet、Android 的分享菜单,用户装了什么 App 就能分享到哪。你唯一要做的是加一层降级:不支持的时候回退到复制链接或下载。

问题出在哪

绝大多数移动端项目里的「分享」还是十年前那一套:页脚排一排图标,微信、微博、QQ、朋友圈,每个都对应一段自己拼的跳转 URL。这套东西有三个说不出口的毛病:

  • 你永远凑不齐全平台。国内用户装了小红书、钉钉、飞书,海外用户装的是 WhatsApp、Telegram、VK——你写死哪几个,就漏掉哪几个。
  • 每个图标背后往往还挂着一个第三方脚本或统计像素。为了几个按钮,页面多几个请求、多几 KB,还顺带把用户行为送了出去。
  • 最尴尬的是微信内置浏览器。你那排按钮里的「微信分享」在微信里点开时,其实什么都分享不了,只能提示用户点右上角菜单——用户早就烦了。

而用户真正想要的,只是「把这个链接发给我的同事」。这件事在原生 App 里是一次点击的事,在网页里却被做成了选择题。

浏览器其实早就给了标准答案

Web Share API 的核心就两个方法:

// 1. 先判断能不能分享
if (navigator.canShare && navigator.canShare({ files: [file] })) {
  // 2. 唤起系统原生分享面板
  await navigator.share({
    title: '文章标题',
    text: '一句推荐语',
    url: location.href,
    files: [file], // 可选,分享文件
  });
}

它的设计哲学和原生 App 完全一致:你不决定用户分享到哪,系统面板决定。用户手机里装了哪些 App,面板里就出现哪些,包括最近联系人。你不用维护一张永远维护不全的平台清单。

这里有两个必须记住的细节。

第一,navigator.share() 必须在用户手势(user activation)里调用,也就是绑定在 click/tap 事件里,不能放在定时器或异步链的后半段随手动。

第二,分享文件要先过 navigator.canShare({ files })。传一个 File 对象数组进去,图片、PDF 都能走系统分享面板,用户可以直接分享到微信聊天窗口,而不是先下载到相册再自己找。

const data = { files: [new File([blob], 'chart.png', { type: blob.type })] };
if (navigator.canShare(data)) {
  await navigator.share(data);
}

支持度分布得很「移动优先」

这正是它最值得你现在就用的原因——它在移动端早就稳了:

  • Android Chrome:share() 从 Chrome 61 就全量支持,files 参数从 Chrome 76 起支持。
  • iOS Safari:share() 从 12.1 起支持,files 从 14 起支持。
  • 桌面 Chrome / Edge:文字和链接分享在 89 及以后已全量;但桌面 Firefox 至今不支持。

换句话说,你把它当作移动端渐进增强来用是最舒服的:移动端直接走原生面板,桌面端回退到复制链接。这不是「能用但凑合」,而是它本来就是为你这么设计的。

一个真实的降级写法

关键是把「能不能分享文件」和「能不能分享」分开判断,别一把梭:

const canShareFiles = (files) =>
  navigator.canShare && navigator.canShare({ files });

async function shareOrCopy({ title, text, url, files }) {
  // 能分享文件:走文件分享
  if (files?.length && canShareFiles(files)) {
    try {
      await navigator.share({ title, text, files });
      return;
    } catch (err) {
      if (err.name === 'AbortError') return; // 用户主动取消,不算失败
    }
  }
  // 只分享链接 / 文字
  if (navigator.share) {
    try {
      await navigator.share({ title, text, url });
      return;
    } catch (err) {
      if (err.name === 'AbortError') return;
    }
  }
  // 最终降级:复制链接
  await navigator.clipboard.writeText(url);
  toast('链接已复制');
}

注意 AbortError 那段——用户关掉面板是正常行为,别当成异常弹错误提示。这是最常见的体验 bug。

值得参考的数据

Google 的 Goibibo PWA 案例里,团队明确提到采用 Web Share API 来拉平「网页版」和「iOS/Android App 版」的体验差距,让分享酒店、车次更顺手;整个 PWA 改造后对比旧的移动网页流程,转化率提升了 60%。分享入口顺不顺,确实会影响用户愿不愿意把这个页面传出去。

另一个值得抄的做法来自一些内容站:他们干脆把页脚那排社交按钮整排删掉,只留一个原生分享按钮,零外部脚本、零跟踪——用户手机上装了 60% 以上的流量都来自移动端时,这排按钮本来也没发挥作用。

下一步你可以这么做

  1. 把你的分享函数从「拼接各平台 URL」改成「调 navigator.share() + 复制链接降级」,能删掉一大批代码。
  2. 如果你的产品有「分享图片/报表/优惠券」的需求,试试 canShare({ files }),让用户直接分享文件到聊天窗口,别再让他先下载。
  3. 桌面端保留复制链接或传统按钮,移动端优先原生面板——按 navigator.canShare 分流,而不是按 UA 猜。

最后留一个不用绕开的现实:微信内置浏览器里,navigator.share 不可用,分享仍然只能靠用户点右上角菜单。这一点没有任何 API 能绕过,老老实实提示用户即可——别为它再写一堆没用的按钮。

评论区

0 条评论

登录后可评论。

阿跨·跨端开发 712 阅读