js中navigator.clipboard的兼容性問題
問題描述
在實現(xiàn)快捷復(fù)制的時候出現(xiàn)的一個問題,使用navigator.clipboard實現(xiàn)復(fù)制的時候,在本地測試沒有問題,但是上線之后復(fù)制不能正常使用。
問題分析
這個問題可能是由于瀏覽器安全策略導(dǎo)致的。在本地開發(fā)環(huán)境中,navigator.clipboard API 可以正常工作,但在生產(chǎn)環(huán)境中,由于安全限制,只有在以下條件下才能使用剪貼板API:1. 網(wǎng)站必須使用HTTPS協(xié)議;2. 網(wǎng)頁必須處于活動標(biāo)簽頁;3. 用戶必須已經(jīng)授予剪貼板權(quán)限。建議檢查生產(chǎn)環(huán)境是否滿足這些條件,特別是HTTPS協(xié)議的支持情況。如果確實是HTTPS環(huán)境,那么可能是瀏覽器沒有正確授予剪貼板權(quán)限,或者在某些瀏覽器中clipboard API的支持存在兼容性問題。但是我使用同一個瀏覽器,排除瀏覽器兼容,發(fā)現(xiàn)是上線之后的協(xié)議是http協(xié)議。
解決方案
由于環(huán)境使用的是HTTP協(xié)議,而navigator.clipboard API在非HTTPS環(huán)境下會受到安全策略限制。有以下解決方案:1. 將網(wǎng)站升級到HTTPS協(xié)議(推薦);2. 使用傳統(tǒng)的document.execCommand(‘copy’)方法作為降級方案;3. 如果必須使用HTTP,可以考慮使用第三方復(fù)制庫如clipboard.js作為替代方案。因為使用什么協(xié)議不是我決定的,所以最后用傳統(tǒng)的document.execCommand(‘copy’)做降級處理。
代碼:
降級之前代碼
<template>
<div class="text-container" @mouseenter="showButton = true" @mouseleave="showButton = false">
<!-- 復(fù)制按鈕,僅在鼠標(biāo)懸停時顯示 -->
<el-tooltip placement="top" content="復(fù)制">
<el-icon v-if="showButton" class="copy-button" @click="handleCopy"><CopyDocument /></el-icon>
</el-tooltip>
<!-- 顯示的內(nèi)容 -->
<div class="content">
<slot></slot>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { CopyDocument } from "@element-plus/icons-vue";
import { message } from "@/utils/message";
// 定義 Props
const props = defineProps({
text: {
type: String,
required: true // 必填項,表示需要復(fù)制的文字
}
});
// 控制復(fù)制按鈕的顯示狀態(tài)
const showButton = ref(false);
// 復(fù)制文本到剪貼板
const handleCopy = () => {
navigator.clipboard
.writeText(props.text)
.then(() => {
message("復(fù)制成功", { type: "success" });
})
.catch(err => {
console.error("復(fù)制失敗:", err);
message("復(fù)制失敗", { type: "error" });
});
};
</script>
<style lang="scss">
/* 基本樣式 */
.text-container {
position: relative; /* 父容器設(shè)置為相對定位 */
display: block;
padding: 0 10px;
min-height: 24px; /* 確保容器有足夠的高度 */
}
/* 內(nèi)容區(qū)域 */
.content {
padding-right: 30px; /* 為圖標(biāo)預(yù)留空間 */
word-break: break-word; /* 允許文字換行 */
}
/* 復(fù)制按鈕樣式 */
.copy-button {
position: absolute;
top: 50%;
right: 10px; /* 固定在最右側(cè)并留出一些間距 */
transform: translateY(-50%); /* 垂直居中 */
color: #409eff;
cursor: pointer;
font-size: 16px;
transition: all 0.3s;
&:hover {
color: #66b1ff;
}
}
/* 使用偽類創(chuàng)建背景區(qū)域 */
.copy-button::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 32px; /* 背景寬度 */
height: 32px; /* 背景高度 */
background-color: rgba(0, 0, 0, .03); /* 背景顏色和透明度 */
border-radius: 6px; /* 圓角效果 */
z-index: -1; /* 確保背景區(qū)域在圖標(biāo)后面 */
opacity: 0; /* 默認隱藏 */
transition: opacity 0.3s; /* 平滑過渡效果 */
}
/* 懸停時顯示背景區(qū)域 */
.copy-button:hover::after {
opacity: 1; /* 顯示背景 */
}
</style>
優(yōu)雅降級之后
<template>
<div class="text-container" @mouseenter="showButton = true" @mouseleave="showButton = false">
<!-- 復(fù)制按鈕,僅在鼠標(biāo)懸停時顯示 -->
<el-tooltip placement="top" content="復(fù)制">
<el-icon v-if="showButton" class="copy-button" @click="handleCopy"><CopyDocument /></el-icon>
</el-tooltip>
<!-- 顯示的內(nèi)容 -->
<div class="content">
<slot></slot>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { CopyDocument } from "@element-plus/icons-vue";
import { message } from "@/utils/message";
// 定義 Props
const props = defineProps({
text: {
type: String,
required: true // 必填項,表示需要復(fù)制的文字
}
});
// 控制復(fù)制按鈕的顯示狀態(tài)
const showButton = ref(false);
// 復(fù)制文本到剪貼板
const handleCopy = async () => {
try {
// 優(yōu)先使用 navigator.clipboard API
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(props.text);
message("復(fù)制成功", { type: "success" });
return;
}
// 降級使用 document.execCommand
const textArea = document.createElement('textarea');
textArea.value = props.text;
document.body.appendChild(textArea);
textArea.select();
const successful = document.execCommand('copy');
document.body.removeChild(textArea);
if (successful) {
message("復(fù)制成功", { type: "success" });
} else {
message("復(fù)制失敗", { type: "error" });
}
} catch (err) {
console.error("復(fù)制失敗:", err);
message("復(fù)制失敗", { type: "error" });
}
};
</script>
<style lang="scss">
/* 基本樣式 */
.text-container {
position: relative; /* 父容器設(shè)置為相對定位 */
display: block;
padding: 0 10px;
min-height: 24px; /* 確保容器有足夠的高度 */
}
/* 內(nèi)容區(qū)域 */
.content {
padding-right: 30px; /* 為圖標(biāo)預(yù)留空間 */
word-break: break-word; /* 允許文字換行 */
}
/* 復(fù)制按鈕樣式 */
.copy-button {
position: absolute;
top: 50%;
right: 10px; /* 固定在最右側(cè)并留出一些間距 */
transform: translateY(-50%); /* 垂直居中 */
color: #409eff;
cursor: pointer;
font-size: 16px;
transition: all 0.3s;
&:hover {
color: #66b1ff;
}
}
/* 使用偽類創(chuàng)建背景區(qū)域 */
.copy-button::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 32px; /* 背景寬度 */
height: 32px; /* 背景高度 */
background-color: rgba(0, 0, 0, .03); /* 背景顏色和透明度 */
border-radius: 6px; /* 圓角效果 */
z-index: -1; /* 確保背景區(qū)域在圖標(biāo)后面 */
opacity: 0; /* 默認隱藏 */
transition: opacity 0.3s; /* 平滑過渡效果 */
}
/* 懸停時顯示背景區(qū)域 */
.copy-button:hover::after {
opacity: 1; /* 顯示背景 */
}
</style>
到此這篇關(guān)于js中navigator.clipboard的兼容性問題的文章就介紹到這了,更多相關(guān)navigator.clipboard兼容性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
uni-app如何頁面?zhèn)鲄?shù)的幾種方法總結(jié)
這篇文章主要介紹了uni-app如何頁面?zhèn)鲄?shù)的幾種方法總結(jié),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
原生js提示框并自動關(guān)閉(手工關(guān)閉)
今天在寫后臺交互的時候原來都是用alert太難看每次都需要點擊一下才可以,比較麻煩所以特整理了幾個比較好的js提示框代碼,方便提示一下2023-04-04
JavaScript判斷數(shù)組是否存在key的簡單實例
下面小編就為大家?guī)硪黄狫avaScript判斷數(shù)組是否存在key的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-08-08
關(guān)于TypeScript應(yīng)該盡量避免的語法總結(jié)
TypeScript是JavaScript的超集,具有類型系統(tǒng),支持ES6語法,支持面向?qū)ο缶幊痰母拍?下面這篇文章主要給大家介紹了關(guān)于TypeScript應(yīng)該盡量避免的語法,需要的朋友可以參考下2022-04-04
Chrome瀏覽器的alert彈窗禁止再次彈出后恢復(fù)的方法
本文主要介紹了Chrome瀏覽器的alert彈窗禁止再次彈出后恢復(fù)的方法。具有一定的參考價值,下面跟著小編一起來看下吧2016-12-12
bootstrap模態(tài)框彈出和隱藏,動態(tài)改變中間內(nèi)容的實例
今天小編就為大家分享一篇bootstrap模態(tài)框彈出和隱藏,動態(tài)改變中間內(nèi)容的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08

