react中clipboard複製內容需點擊兩次才生效的解決方案

關於clipboard的複製功能及使用方法,相信大家並不陌生,難的是如何解決首次點擊兩次才複製成功的問題?

這個問題真的是糾結了我好長時間,好在最後也算是有了解決的方法,接下來簡單說一下怎麼使用以及點擊兩次才生效的解決辦法。

1、在項目中下載所需要的依賴:

npm install clipboard --save

2、點擊複製鏈接,實現複製

先說一下正常的情況,一般是這樣:

方案一

// html
<a id="copyBtn" data-clipboard-text="複製的內容" onClick={() => copy()} >複製鏈接</a>
// js
copyWarrantLink = () => {
    let clipboard = new Clipboard('#copyBtn');
    clipboard.on('success', function(e) {
        console.log("複製成功");
        clipboard.destroy();
    })
}

方案二

// html
<a id="copyBtn" onClick={() => copy()} >複製鏈接</a>
// js
copy = () => {
    let clipboard = new Clipboard('#copyBtn',{
        text: () => "複製的內容"
    });
    clipboard.on('success', function(e) {
        console.log("複製成功");
        clipboard.destroy();
    })
}

這種情況下,複製的問題是不大的。但你很快就能發現首次複製是無效的,必須點擊兩次才能夠解決。

之前我居然天真的以爲我項目中需要點擊兩次才成功是因爲我需要複製的文本是動態的,結果發現,靜態的也是這樣。。。

項目中的需求是點擊複製鏈接動態獲取地址,也就是需要通過請求來動態更新url的地址,具體如下:

// html
<a id="copyBtn" data-clipboard-text={getLink} onClick={() => copy()} >複製鏈接</a>
// js
// 此處省略了複製的代碼
copy = () => {
    let params = {};
    axios.post(url, params).then((result) => {
        this.setState({getLink: result});
    }) 
}

和之前兩個例子差不多,唯一不同的就是複製的文本是從請求中拿的,蒐羅了一下網上的解決方案,大抵是以下幾種:

  • 請求變爲同步,不使用異步請求
  • 設置setTimeOut,延遲執行
  • 創建對象不應該寫在方法裏面,應該在頁面加載完成之後就創建
  • 手動添加一次點擊事件

經過實踐,我發現前面三種解決方案對我來說好像並沒有什麼效果(可能是我的打開方式不對?)

emm,所以我採用的是第四種,手動添加點擊事件。但是,使用這種方法的時候也要注意不要在方法裏調用呀,否則會陷入死循環的。

爲了避免重複發請求,在點擊複製鏈接的時候我先進行了判斷,具體代碼如下:

// html
<a id="copyBtn" data-clipboard-text={getLink} onClick={() => beforeCopy()} >複製鏈接</a>
// js
let copyBtn = null;
// 頁面渲染完成後創建一個對象
componentDidMount = () => {
    let obj = this;
    copyBtn = new Clipboard('#copyWarrantLinkBank');

    copyBtn.on('success', function(e) {
        console.log("複製成功");
        // 複製成功之後銷燬
        copyBtn.destroy();  
        obj.setState({getLink: ""})
    })
}
// 監聽複製文本的變化
componentDidUpdate (prevProps, prevState) {
    let obj = this;
    if(prevState.getLink !== this.state.getLink && document.getElementById("copyBtn")){
        if(this.state.getLink) {
            // 手動點擊一次
            document.getElementById("copyBtn").click();
            copyBtn = new Clipboard('#copyBtn');

            copyBtn.on('success', function(e) {
                console.log("複製成功");
                copyBtn.destroy();  
                obj.setState({getLink: ""})
            })
        }
    } 
}

// 在調用請求之前,先判斷複製的文本是否爲空
beforeCopy = () =>{
    if(this.state.getLink){
        return
    }else{
        this.copy();
    }
}

// 發請求獲取複製的文本信息
copy = () => {
    let params = {};
    axios.post(url, params).then((result) => {
        this.setState({getLink: result});
    }) 
}

簡單說一下流程:

  • getLink是一個狀態值,初始值是空
  • 點擊複製鏈接,getLink爲空,調用copy的方法獲取複製文本
  • 此時的componentDidUpdate中的條件是滿足的,所以手動點擊一次
  • 點擊後調用beforeCopy方法,此時getLink已經有值啦,就不會再發請求了

這裏需要注意的是在頁面渲染完成後需創建一個對象,這裏主要是用於第一次的時候,在複製成功後銷燬創建的對象,並將getLink置空,這樣後面才能進行判斷。

當然,這個方法也可能還有不足的地方,期待後面有更好的解決方案。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章