iT邦幫忙

0

【JS】如何限制delete鍵只能發送一次?

  • 分享至 

  • xImage

大家好,
關於限制delete鍵只能發送一次,
我有兩個架構方式,想請教哪個比較好?
或者有哪種更好的寫法?

首先先做個假資料

<head>
    <style>
        .theBtn {
            margin: 0 5px;
        }
    </style>
</head>
<body>
    <div id="myDiv"></div>
    <script>
        const myDiv = document.querySelector('#myDiv')

        //假資料data
        const data = (function () {
            let result = []
            for (let index = 0; index < 30; index++) {
                result.push(index)
            }
            return result
        }())
    </script>
</body>

【方法一】 所有的delete鍵,都共用同一個變數isClicked
優點:當delete鍵有上百個以上時,可以省下不少記憶體空間,且比較不會有bug。
缺點:當刪除A時,必須等收到A的response後,才能刪除B。使用者體驗較差。

const theBtn = (id, isClicked = false) => {
    return function () {
        if (!isClicked) {
            isClicked = true
            //用setTimeout代替fetch來測試
            setTimeout(() => {
                isClicked = false
                console.log('response', id);
            }, 2000)
        }
    }
}
for (let index = 0; index < data.length; index++) {
    let button = document.createElement('button')
    button.id = index
    button.innerText = '我是' + index
    button.classList = 'theBtn'

    button.onclick = theBtn(index)
    myDiv.append(button)
}

【方法二】 所有的delete鍵,都有各自的變數isClicked
優點:不必等A的response,就能刪除B。使用者體驗較佳。
缺點:會占用較多的記憶體空間去存放變數isClicked,且可能會有bug(當A刪除失敗時,可能會影響B鍵刪除的正確性)

for (let index = 0; index < 10; index++) {
    let button = document.createElement('button')
    button.id = index
    button.innerText = '我是' + index
    button.classList = 'theBtn'

    button.onclick = (function (isClicked) {
        return function () {
            if (!isClicked) {
                isClicked = true
                setTimeout(() => {
                    isClicked = false
                    console.log('response', index);
                }, 2000)
            }
        }
    }(false))
    myDiv.append(button)
}

不曉得哪種架構會比較好?

另外我將這兩種架構,用vue去寫。
覺得自己寫得很繁瑣,想請教能否再精簡寫法?

<template>
  <div>
    <button v-for="(id, index) in data" :key="'data' + index"
      @click="theBtn(id)">我是{{ index }}</button>
  </div>
</template>

【法一】

<script setup>
    const theBtn = (function (isClicked) {
        return function (id) {
            if (!isClicked) {
                isClicked = true
                setTimeout(() => {
                    isClicked = false
                    console.log('response', id);
                }, 2000)
            }
        }
    }(false))
</script>

【法二】(覺得很繁瑣)
因為vue的@click是綁定同一個theBtn,
所以只好先將所有的isClicked,都存在同一個陣列isClicked_array裡

<script setup>
    const theBtn = (function (array) {
        let isClicked_array = array.map(e=>false)
        return function (id) {
            if (!isClicked_array[id]) {
                isClicked_array[id] = true
                setTimeout(() => {
                    isClicked_array[id] = false
                    console.log('response', id);
                }, 2000)
            }
        }
    }(data))
</script>
看更多先前的討論...收起先前的討論...
froce iT邦大師 1 級 ‧ 2023-01-31 12:39:25 檢舉
你是要同類的按鍵只能按一次,並且送到後端檢查?
是的話按下去就直接disable設為true,跳modal出來告訴使用者在處理中,如果傳送失敗後再把disable設為false就好。

等傳回結果後再處理,使用者會亂按。

另外處理方法我會選1,一個開關變數就行了。
greenriver iT邦研究生 5 級 ‧ 2023-01-31 12:57:24 檢舉
不是耶,是後台資料,通常好幾筆,想刪除某一筆時,為了防止使用者一秒連按十幾次,結果相同id的request會傳了十幾次。
jyo238 iT邦新手 5 級 ‧ 2023-01-31 13:43:25 檢舉
那不就跟froce的情境一樣嗎?一般來說就是用modal跟disabled來防止使用者一秒連按十幾次
froce iT邦大師 1 級 ‧ 2023-01-31 13:47:24 檢舉
重點還是你不能等傳回結果後再處理,按下去的瞬間你就要先disable了。

有空再寫範例,這會有點小複雜。
froce iT邦大師 1 級 ‧ 2023-01-31 13:48:03 檢舉
> 那不就跟froce的情境一樣嗎?一般來說就是用modal跟disabled來防止使用者一秒連按十幾次

他這個應該用不到modal。modal是控制/阻塞整個頁面用的。
認同froce+1
送出時,JS 鎖住畫面,不讓User重複按。( 這樣寫比較簡單 )。
揮揮手 iT邦研究生 5 級 ‧ 2023-01-31 14:26:11 檢舉
認同
當下按下去 就應該讓該row 消失
更正 那看來還是紀錄狀態變更最後統一處理
感覺比較好

還是你們流程一定要這樣走?
froce iT邦大師 1 級 ‧ 2023-01-31 15:05:08 檢舉
> 當下按下去 就應該讓該row 消失

這個不行,萬一網路慢或系統出問題,會使使用者以為操作完成了,但實際上還沒刪掉。
建議先disable button,確認沒問題後再刪除row。
如果是ajax....有個套件可以做遮罩阻止這種事 == > jQuery BlockUI
的確有時會遇到神經病使用者,沒事在那邊蝦按
chiayinin iT邦新手 4 級 ‧ 2023-02-01 16:10:08 檢舉
若是這樣寫可以嗎?
@click.once="theBtn(id)"
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

1
froce
iT邦大師 1 級 ‧ 2023-01-31 14:54:43
最佳解答

playground

<script setup>
import { ref } from 'vue'
  
const items = ref([{'id':1, "name":"aaa"}, {'id':2, "name":"bbb"}])

const delthis = async (item)=>{
  const copyedItem = JSON.parse(JSON.stringify(item))
  item.disabled = true
  
// 傳送到後端,如果操作成功就直接從items刪掉,假設回傳的是刪除的id
// 失敗就恢復disabled的狀態
//  send(copyedItem).then((res)=>{
//    const index = items.findIndex((item)=>item.id==res.id)
//    items.splice(index, 1)
//  }).catch((e)=>{
//    const item = items.find((item)=>item.id==res.id)
//    delete item.disabled
//    console.log(e)
//  })

}
</script>

<template>
  <div v-for="item in items" :key="item.id">
    <span :data-id="item.id">{{item.name}}</span>
    <button @click="delthis(item)" :disabled="item.disabled">del</button>
  </div>
</template>
greenriver iT邦研究生 5 級 ‧ 2023-01-31 16:59:30 檢舉

原來如此
謝謝你~~
/images/emoticon/emoticon41.gif

0
Oo_花之舞__oO
iT邦新手 1 級 ‧ 2023-02-01 05:21:00

這似乎有個名詞叫做,防抖。

我要發表回答

立即登入回答