el-table绑定的相同事件怎么去区分他们?

6/14/2023

最近项目中有这么一个需求, 表格的操作栏的每一行中都有一个 '导出内容' 按钮 ,点击按钮导出对应通道的内容, 对于同一个导出按钮要求在30秒内不能重复触发导出事件, 30秒内重复点击给出提示。

通道ID 通道名称 通道内容来源 操作
00089 测试通道 新闻资讯 导出内容
00065 回归测试通道 环球新闻 导出内容
00066 开发阶段通道 人民日报 导出内容

对于这个需求, 想必大家第一时间就想到了节流

<el-button @click='exportChannelContent(scope.row.id)'>导出内容</el-button>

//导出内容
const exportChannelContent = throttle(handleExport, exportTip, 30 * 1000)
async function handleExport(channelId: string) {
    const params = {id:channelId}
   //调接口开始导出 do something.....
}
function exportTip() {
    //提示
    ElMessage({
        message: '请勿短时内重复导出',
        type: 'warning'
    })
}
//节流( 时间戳、定时器皆可 )
export function throttle(fn: any,fn2:any, interval: number) {
    let lastTime = 0
    return function (this: any, ...args: any[]) {
        // 获取当前时间戳
        const nowTime = new Date().getTime()
        // cd剩余时间
        const remainTime = nowTime - lastTime
        // 节流时间间隔外
        if (remainTime - interval >= 0) {
            //执行传入的导出事件
            fn.apply(this, args)
            // 将上一次函数执行的时间设置为触发事件时的时间
            lastTime = nowTime
        } else {
            //delay时间间隔内重复触发事件提示
            fn2()
        }
    }
}

写好了, 测试一手.....发现,点击 00089通道对应的'导出内容'按钮后, 30秒内再点击00065通道对应的'导出内容'按钮, 00065通道没有像00089通道一样导出内容,而是提示'请勿短时内重复导出'。
问题 : 其实就是点击每一个 '导出内容'按钮都触发了同一个事件,在30秒内再次触发事件当然就会走进节流函数的 else 的提示里
解决 : 最先想到的是用元素的索引来区分每行的 导出内容按钮,在这个地方使用索引作为判断依据有个缺陷,这个地方的 el-table是带分页功能的,假如点了第一页的第一个,然后在30秒内切换到第二页点击第一个还是会走进else里给出提示,因为他们的索引是相同的,都是0。这时候通道ID就派上用场了,可以把它作为唯一性的判断依据,对上面的节流函数做一下调整。

//节流
export function throttle(fn: any,fn2:any, interval: number) {
    let lastTime = 0
    let channelId = '' //点击导出时-用于区分不同的通道对应的按钮
    return function (this: any, ...args: any[]) {
        // 获取当前时间
        const nowTime = new Date().getTime()
        // cd剩余时间
        const remainTime = nowTime - lastTime
        // 节流时间间隔外 或者 点击了其他通道的导出皆可触发导出
        if (remainTime - interval >= 0 || channelId !== args[0]) {
            fn.apply(this, args)
            //将上一次导出时对应的通道ID存在内存中
            channelId = args[0]
            // 将上一次函数执行的时间设置为触发事件时的时间
            lastTime = nowTime
        } else {
            //delay时间间隔内重复触发事件提示
            fn2()
        }
    }
}

handleExport 函数传入的 channelId 作为内部闭包函数访问到的外部变量会存储在内存当中,每次触发事件都会去校验点击的是不是上一次的通道ID对应的 '导出内容'按钮, 这样这个需求就搞定了。