微信公众号 - 禁用 H5 网页长按图片时弹出的菜单(转发给朋友 / 保存到手机 / 收藏 / 搜一搜),苹果安卓系统都可暴力 100% 完美禁用菜单,任何前端框架、任何浏览器都适用的解决方案

前言

关于微信公众号 H5 网站禁用长按弹出菜单的教程,网上的解决方案几乎都不好使,要么不兼容要么代码臃肿。

本文实现了 公众号网站或普通网站开发,强力禁用 “长按图片” 时弹出的微信菜单,

支持 Vue2 / Vue3 语法,按照本文提供的代码,保证任何前端技术、任何苹果安卓系统都可行有效 100% 禁用,


如下图真机运行测试,注意看 “屏幕圆圈光标触摸位置”,无论怎么长按都不会出现菜单了。

您可以选择只给 "某个" 图片禁用,也可以直接给整页全部禁用!

在这里插入图片描述

解决方案

可参考如下代码,应用到您的项目中。

<think>我们正在解决在iOS设备(特别是微信H5环境)中,uniapp使用剪贴板功能失败的问题。根据引用[1],iOS微信H5禁止在异步函数中复制内容到剪贴板,所以我们需要将复制操作放在同步上下文中,或者使用其他方法绕过限制。 引用[3]提供了一种全端解决方案,通过使用vue-clipboard2插件,在H5环境下使用该插件的复制方法,而在非H5环境(如App和小程序)使用uni-app自带的uni.setClipboardData方法。 另外,引用[4]展示了使用v-clipboard指令的方式,但需要注意的是,这种方式依赖于vue-clipboard2插件。 因此,我们可以采用以下步骤: 1. 安装vue-clipboard2插件。 2. 在main.js中引入并挂载该插件。 3. 在组件中,根据平台条件编译,分别使用不同的复制方法: -H5环境下,使用vue-clipboard2提供的`this.$copyText`方法(注意:该方法返回一个Promise,所以是异步的,但在H5环境下,除了iOS微信内,其他浏览器通常允许异步复制。针对iOS微信内,我们需要特殊处理,将复制操作放在同步上下文中?但是根据引用[3]的代码,它并没有特别处理iOS微信内的同步问题,而是直接使用了`this.$copyText`,这可能在iOS微信内仍然失败。所以我们需要调整:在iOS微信内,避免使用异步的复制方法,而使用同步的方法?然而,在H5中,复制操作通常是异步的,因为navigator.clipboard.writeText是异步的。因此,我们需要寻找一种同步方法,但事实上,现代浏览器已经不再提供同步的剪贴板API。 重新审视引用[1]的解决方案:将复制操作移动到异步函数之外。也就是说,在请求的then函数之外执行复制操作。但是,如果我们复制的内容是从异步请求中获取的,那么我们必须等待请求完成才能复制,这就形成了异步。所以,我们需要在请求完成后,通过某种方式让复制操作在同步上下文中执行?实际上,我们可以通过用户交互(如点击按钮)来触发复制操作,因为用户交互是同步的,所以我们可以将复制操作放在一个按钮的点击事件处理函数中,并且这个事件处理函数是同步执行的。但是,如果我们的复制操作依赖于请求结果,那么我们需要在请求完成后自动复制,这时就无法避免异步。因此,我们需要在请求完成后,通过一个用户交互(比如弹出一个提示,让用户点击一个按钮来复制)来触发复制操作,这样复制操作就在用户点击的同步事件中执行。 但是,如果不想增加用户操作,我们可以尝试使用另一种方法:在iOS微信内,使用document.execCommand('copy'),这个命令是同步的,但需要在一个可编辑的元素中选中文本。具体步骤: - 创建一个隐藏的textarea,设置其value为要复制的文本。 - 将textarea添加到文档中。 - 选中textarea中的文本。 - 执行document.execCommand('copy')。 - 移除textarea。 由于document.execCommand('copy')是同步的,所以可以在异步函数中执行,但要注意,iOS微信内可能仍然有安全限制,不过根据经验,这种方式在iOS微信内是可行的。 因此,我们可以写一个函数,在iOS微信环境下使用这种方式,其他环境使用原来的方式。 但是,在uniapp中,我们如何判断是iOS微信环境?我们可以通过navigator.userAgent来判断。 在uniapp中,我们可以使用条件编译,在H5环境下使用自定义的复制方法(包括处理iOS微信),非H5环境使用uni.setClipboardData。 具体实现: 1.H5环境下,我们判断如果是iOS的微信浏览器,则使用document.execCommand('copy')的方式,否则使用navigator.clipboard.writeText(或者vue-clipboard2内部也是使用这种方式,但为了直接控制,我们可以自己实现)。 2. 在非H5环境(App、小程序)下,使用uni.setClipboardData。 但是,引用[3]中已经使用了vue-clipboard2,它在H5环境下是异步的(使用Promise),所以我们需要修改H5环境下的复制方法,特别是针对iOS微信。 我们可以这样设计: -H5环境下,我们不再使用vue-clipboard2的异步复制,而是自己实现一个同步复制方法(使用document.execCommand)用于iOS微信,其他浏览器使用异步复制(因为现代浏览器推荐异步API,且execCommand已废弃)。 步骤: 1. 安装vue-clipboard2(为了非iOS微信H5环境,我们仍然可以使用它,但为了统一,我们可以自己实现一个通用的方法,避免插件在iOS微信上失效)。 2. 在复制方法中,判断环境: ```javascript copyText() { // #ifdef H5 // 判断是否为iOS微信环境 const ua = window.navigator.userAgent; const isIOS = /iPhone|iPod|iPad/i.test(ua); const isWechat = /MicroMessenger/i.test(ua); if (isIOS && isWechat) { // 使用同步复制方法 this.copyByExecCommand(this.text); } else { // 使用异步复制方法,这里使用vue-clipboard2的$copyText或者使用navigator.clipboard.writeText // 注意:navigator.clipboard.writeText在非https环境下可能不可用,所以我们可以使用execCommand作为降级方案,但考虑到非iOS微信环境,我们可以使用vue-clipboard2,它内部已经做了降级处理。 this.$copyText(this.text).then(() => { this.showToast('复制成功'); }).catch(() => { this.showToast('复制失败'); }); } // #endif // #ifndef H5 uni.setClipboardData({ data: this.text, success: () => { this.showToast('复制成功'); }, fail: () => { this.showToast('复制失败'); } }); // #endif }, copyByExecCommand(text) { const textarea = document.createElement('textarea'); textarea.value = text; textarea.readOnly = true; textarea.style.position = 'absolute'; textarea.style.left = '-9999px'; document.body.appendChild(textarea); textarea.select(); textarea.setSelectionRange(0, textarea.value.length); // 选中所有内容 try { if (document.execCommand('copy')) { this.showToast('复制成功'); } else { this.showToast('复制失败'); } } catch (err) { this.showToast('复制失败'); } document.body.removeChild(textarea); }, showToast(title) { uni.showToast({ title, icon: 'none' }); } ``` 注意:在H5环境下,我们使用了条件编译,所以这段代码只在H5平台有效。在非H5平台,我们使用uni.setClipboardData。 但是,上面的代码中,在H5环境下,我们并没有使用vue-clipboard2插件,而是自己实现了复制。那么之前安装的vue-clipboard2插件就没有用上。我们可以不使用该插件,或者只使用它的指令方式(如果我们喜欢指令方式的话)。但为了代码简洁,我们可以不用插件,自己控制。 另外,在非iOS微信H5环境下,我们使用了`this.$copyText`,这需要vue-clipboard2插件。如果我们不想使用插件,也可以自己实现异步复制: ```javascript // 替代this.$copyText copyByAsync(text) { if (navigator.clipboard) { return navigator.clipboard.writeText(text).then(() => { return true; }).catch(err => { console.error('Async: Could not copy text: ', err); return false; }); } else { // 如果不支持navigator.clipboard,则使用execCommand作为降级 return new Promise((resolve, reject) => { try { const result = this.copyByExecCommand(text); resolve(result); } catch (err) { reject(err); } }); } } ``` 然后修改上面的代码: ```javascript // #ifdef H5 const ua = window.navigator.userAgent; const isIOS = /iPhone|iPod|iPad/i.test(ua); const isWechat = /MicroMessenger/i.test(ua); if (isIOS && isWechat) { this.copyByExecCommand(this.text); } else { this.copyByAsync(this.text).then(success => { this.showToast(success ? '复制成功' : '复制失败'); }); } // #endif ``` 这样我们就不需要依赖vue-clipboard2插件了。 总结步骤: 1. 在项目中,我们不需要安装vue-clipboard2插件,而是自己实现复制方法。 2. 在复制方法中,使用条件编译,区分H5和非H5。 3.H5中,区分iOS微信环境和其他环境,分别使用同步复制(execCommand)和异步复制(优先使用navigator.clipboard.writeText,不支持则使用execCommand)。 4. 在非H5环境,使用uni.setClipboardData。 但是,注意:在H5环境下,execCommand方法在有些环境下可能被禁用,但作为降级方案是可行的。 另外,在iOS微信环境中,使用execCommand方法需要用户交互(比如点击事件)的同步上下文中执行。在我们的代码中,复制操作是由用户点击按钮触发的,所以是同步上下文,因此是可行的。 最后,我们给出完整的实现代码示例(假设不需要vue-clipboard2插件):</think>在苹果设备的 UniApp 中实现剪贴板功能时,iOS 微信H5 环境存在特殊限制。以下是完整解决方案: ### 解决方案苹果设备专用) 1. **安装必要插件** ```bash npm install vue-clipboard2 ``` 2. **main.js 全局配置** ```javascript import VueClipboard from 'vue-clipboard2' Vue.use(VueClipboard) ``` 3. **页面组件实现** ```html <template> <view> <button @click="copyToClipboard">复制内容</button> </view> </template> <script> export default { data() { return { text: '要复制的文本内容' } }, methods: { async copyToClipboard() { // #ifdef H5 // iOS 微信环境特殊处理 const ua = navigator.userAgent; if (ua.match(/iPhone/i) && ua.match(/MicroMessenger/i)) { this.copyByExecCommand(this.text); } else { await this.$copyText(this.text); uni.showToast({ title: '复制成功' }); } // #endif // #ifdef APP-PLUS uni.setClipboardData({ data: this.text, success: () => uni.showToast({ title: '复制成功' }) }); // #endif }, // iOS 微信专用同步复制方法 copyByExecCommand(text) { const textarea = document.createElement('textarea'); textarea.value = text; textarea.readOnly = true; textarea.style.position = 'absolute'; textarea.style.left = '-9999px'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); uni.showToast({ title: '复制成功' }); } catch (err) { uni.showToast({ title: '复制失败', icon: 'error' }); } finally { document.body.removeChild(textarea); } } } } </script> ``` ### 关键注意事项 1. **iOS 微信限制** - 微信H5 禁止在异步回调(如网络请求 then/catch)中执行复制操作[^1] - 必须使用同步的 `document.execCommand('copy')` 方法 - 需要创建临时的 DOM 元素实现文本选择 2. **环境判断** ```javascript // 检测 iOS 微信环境 const isIOSWechat = /iPhone|iPod|iPad/i.test(navigator.userAgent) && /MicroMessenger/i.test(navigator.userAgent); ``` 3. **多端兼容** - APP 原生环境使用 `uni.setClipboardData` - 非 iOS 微信H5 使用 `$copyText` - 小程序环境自动使用微信原生 API ### 替代方案:指令方式 ```html <text v-clipboard:copy="text" v-clipboard:success="clipboardSuccess" v-clipboard:error="clipboardError"> 点击复制 </text> <script> methods: { clipboardSuccess() { uni.showToast({title: '复制成功'}) }, clipboardError() { // iOS 微信降级处理 if(/iPhone.*MicroMessenger/.test(navigator.userAgent)) { this.copyByExecCommand(this.text); } } } </script> ``` ### 常见问题排查 1. **iOS 复制失效** - 确保不在 `setTimeout` 或网络请求回调中执行 - 必须由真实用户操作(如点击)触发 - 文本内容需要先渲染到 DOM 元素 2. **权限问题** - 在 `manifest.json` 添加剪贴板权限声明: ```json "app-plus": { "distribute": { "ios": { "permissions": { "Clipboard": {} } } } } ``` > **提示**:在苹果设备上测试时,需注意 Safari 浏览器也有类似异步限制,建议统一使用同步方案处理 iOS 所有浏览器环境[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端开发大师鸭

请作者喝杯咖啡 :)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值