- 前端
【免费下载链接】vueuse
Collection of essential Vue Composition Utilities for Vue 3
导读
useShare是 VueUse(packages/core/useShare)中位于Browser分类下的一个组合式函数,它把浏览器原生的 Web Share API(Navigator.share/Navigator.canShare)封装为 Vue 3 的响应式接口,让应用可以用一行代码在移动端与桌面端浏览器中唤起系统级分享面板(分享文本、URL 或文件)。读完本文你将掌握:useShare的基础调用方式、如何通过ref让分享参数保持响应式、isSupported能力检测的原理、share()在参数合并与手势限制方面的底层行为,以及一个可直接落地的组件示例。
什么是 useShare:对 Web Share API 的响应式封装
useShare的作用非常简单直接:它把原生navigator.share()与navigator.canShare()包装成 Vue 的组合式 API 形态。关联文档(skills/vueuse-functions/references/useShare.md)与函数目录文档(packages/core/useShare/index.md)都将其描述为:
Reactive Web Share API. The Browser provides features that can share content in text or file.
也就是说,浏览器本身为页面提供了“以文本或文件形式分享内容”的能力,useShare只是让它接入 Vue 的响应式系统,并在能力不可用时提供优雅的降级。
一个需要特别强调的前提(原文档中以引用块给出):share()必须在用户手势(如按钮点击)中调用,例如不能在页面加载时直接调用,这是浏览器为防止滥用而设计的机制。因此在实现中,share()通常被绑定在按钮的@click事件上。
基础用法:分享标题、文本与 URL
最直接的用法是不传任何参数,仅在调用share()时临时指定分享内容:
import { useShare } from '@vueuse/core' const { share, isSupported } = useShare() function startShare() { share({ title: 'Hello', text: 'Hello my friend!', url: location.href, }) }这段代码中:
share(options)返回一个Promise<void>,用于触发系统分享面板;isSupported是一个响应式的布尔值(ComputedRef<boolean>),用于在 UI 上做能力检测与降级展示。
useShare在@vueuse/core的聚合入口中通过export * from './useShare'(见 packages/core/index.ts)对外导出,因此可以从@vueuse/core直接导入。
分享参数说明
结合 packages/core/useShare/index.ts 的类型定义,分享数据支持以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
title | string | 分享内容的标题 |
text | string | 分享正文文本 |
url | string | 要分享的链接地址,通常传location.href |
files | File[] | 要分享的文件列表(需浏览器与系统同时支持) |
这些字段与原生Navigator.share()的data参数一一对应,且全部为可选。
传入响应式 ref:分享参数随源变化
useShare的签名允许你传入一个MaybeRefOrGetter<UseShareOptions>作为首参。也就是说,你可以传入ref,此时源 ref 的变化会实时反映到后续的分享调用中:
import { ref } from 'vue' const shareOptions = ref<ShareOptions>({ text: 'foo' }) const { share, isSupported } = useShare(shareOptions) shareOptions.value.text = 'bar' share()这里的典型场景是:用户在一个输入框里编辑分享文本,shareOptions.value.text随之更新,之后点击“分享”按钮时,share()拿到的正是最新的内容。仓库中的官方演示 demo.client.vue 正是这样做的:它用一个ref保存{ title, text, url },模板中的<input v-model="options.text">直接双向绑定分享文本,按钮的@click再触发share()。
参数合并的源码细节
从源码看,share()在真正调用原生方法前会做一次合并(packages/core/useShare/index.ts):
const share = async (overrideOptions: MaybeRefOrGetter<UseShareOptions> = {}) => { if (isSupported.value) { const data = { ...toValue(shareOptions), ...toValue(overrideOptions), } // ... } }也就是说:
- 初始化传入的
shareOptions(可能是 ref/getter,通过toValue()取当前值)作为基础; - 每次调用
share()时传入的overrideOptions通过展开运算符覆盖同名键,作为本次分享的最终数据; - 两者合并后的
data才是真正传给navigator.share()的对象。
这解释了为什么原文档说“changes from the source ref will be reflected to your sharing options”——因为每次调用share()时都会重新toValue()求值,响应式源的变化天然生效。
能力检测:isSupported 与 canShare
useShare返回对象继承了 VueUse 的Supportable接口(packages/core/types.ts),即带有isSupported: ComputedRef<boolean>。
在实现中,useShare的判定条件是_navigator && 'canShare' in _navigator(packages/core/useShare/index.ts),并交由 VueUse 的通用工具useSupported(packages/core/useSupported/index.ts)包装成计算属性:
const isSupported = useSupported(() => _navigator && 'canShare' in _navigator)useSupported内部通过computed(() => Boolean(callback()))实现,且依赖useMounted()的挂载状态触发求值,保证在 SSR 环境下安全(defaultNavigator在非浏览器环境为undefined,见 packages/core/_configurable.ts)。也就是说:
- 仅当当前环境存在
navigator且实现了canShare时,isSupported.value才为true; - 在桌面端不支持 Web Share API 的浏览器或 SSR 环境中,
isSupported.value为false。
因此 UI 上应基于isSupported做条件渲染,例如官方 demo 中的做法:不支持时按钮禁用并显示 “Web share is not supported in your browser”,支持时才展示分享输入框与按钮。
share() 内部的二次校验
值得注意的是,share()内部在合并参数后,还会用canShare(data)对本次具体数据再做一次校验(packages/core/useShare/index.ts):
let granted = false if (_navigator.canShare) granted = _navigator.canShare(data) if (granted) return _navigator.share!(data)即使isSupported.value为true,如果某次分享的数据本身不被允许(例如files中混入了平台不支持的文件类型),canShare(data)返回false,则这次调用会静默跳过,不触发系统面板。这一设计让useShare在“能力可用”与“数据可分享”两个层面都做了把关。
类型签名与定制化:ShareOptions、ConfigurableNavigator
useShare的完整类型声明如下(packages/core/useShare/index.ts):
export interface UseShareOptions { title?: string files?: File[] text?: string url?: string } export interface UseShareReturn extends Supportable { share: (overrideOptions?: MaybeRefOrGetter<UseShareOptions>) => Promise<void> }其中share的第二个可选参数overrideOptions同样支持MaybeRefOrGetter,与首参一样会被toValue()求值后参与合并。
此外,useShare还接受第二个参数options?: ConfigurableNavigator。ConfigurableNavigator定义于 packages/core/_configurable.ts:
export interface ConfigurableNavigator { /** * Specify a custom `navigator` instance, e.g. working with iframes or in testing environments. */ navigator?: Navigator }它允许你传入自定义的navigator实例(例如在 iframe 或测试环境中),默认回退到defaultNavigator(即客户端环境下的window.navigator)。这是 VueUse 整个 core 包“可配置全局对象”设计模式的一部分,便于单元测试与跨 iframe 场景。
完整实战示例:可编辑文本的分享按钮
结合官方演示 demo.client.vue 与上述 API,一个可直接运行的组件大致如下:
<script setup lang="ts"> import { useShare } from '@vueuse/core' import { isClient } from '@vueuse/shared' import { ref } from 'vue' const options = ref({ title: 'VueUse', text: 'Collection of essential Vue Composition Utilities!', url: isClient ? location.href : '', }) const { share, isSupported } = useShare(options) function startShare() { // share() 返回 Promise,失败(如用户取消)时需自行捕获 return share().catch(err => err) } </script> <template> <div> <input v-if="isSupported" v-model="options.text" type="text" placeholder="Note" > <button :disabled="!isSupported" @click="startShare"> {{ isSupported ? 'Share' : 'Web share is not supported in your browser' }} </button> </div> </template>要点回顾:
- 分享文本通过
v-model绑定到options.text,点击按钮时share()读取到的始终是最新值; :disabled="!isSupported"保证不支持 Web Share API 的环境不会触发无效调用;share()是异步的,务必.catch()处理用户取消分享或系统拒绝的情况;- 由于浏览器要求用户手势,务必把
share()放在@click回调中,而不是在onMounted等时机直接调用。
小结
useShare是一个小而精的组合式函数:isSupported完成能力检测,share()完成参数合并、canShare二次校验与系统面板唤起,MaybeRefOrGetter的支持让分享参数可以完全响应式。对于需要在移动端提供“分享到微信/系统面板”能力的 Vue 3 应用,它是开箱即用的选择。更多相关工具可以继续查阅 VueUse 函数总览 以及 packages/core/useShare/index.ts 的源码与官方 demo。
- 前端
【免费下载链接】vueuse
Collection of essential Vue Composition Utilities for Vue 3
相关推荐
VueUse useShare 深度指南:在 Vue 3 中响应式封装 Web Share API
VueUse useShare 深度指南:在 Vue 3 中响应式封装 Web Share API 本文以 useShare/index.md https://
前端VueUse useSpeechRecognition:在 Vue 3 中响应式封装 Web 语音识别 API
VueUse useSpeechRecognition:在 Vue 3 中响应式封装 Web 语音识别 API 导读 useSpeechRecognition
前端VueUse useAxios 完全指南:在 Vue 3 中以响应式方式封装 Axios 请求
VueUse useAxios 完全指南:在 Vue 3 中以响应式方式封装 Axios 请求 useAxios 是 VueUse 的 @vueuse/inte
前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考