KarynaSakura 2024-06-10 13:08 采纳率: 41.7%
浏览 2
已结题

TS如何批量添加复制按钮?

需求

有一堆复制按钮和待复制的文本(复制按钮和文本一一对应)

<script>
    Succubus.FetchJSON('包含待复制文本的文件.json')
    .then(data=>{
        var color_value_list = Array(data.length)
        for(var color_index = 0; color_index < data.length; color_index++){
            color_value_list[color_index] = data[color_index]['value']
        }
        document.getElementsByClassName('palette')[0].innerHTML += colorContainerWrite(data)
        ...
    })
</script>

其中省略号部分是添加复制操作的函数/方法。
JSON数据格式:

{
    {
        "name": "灵梦红",
        "value": "#DE3C31"        
    },
    ...
}

我们需要复制其中的"value"

尝试

#1

export function ClipboardCopyByClass(class_id: string, text: Array<string>, success_event_curse: CallableFunction = (function () { }), failed_event_curse: CallableFunction = (function () { console.log('Clipboard Write Failed.') })) {
        var elements = document.getElementsByClassName(class_id)
        for (var i = 0; i < elements.length; i++) {
            var element = elements.item(i) as HTMLElement
            var use_text = ''
            if(i >= text.length){
                use_text = text[text.length - 1]
            }else{
                use_text = text[i]
            }
            element.addEventListener('click', (function () {
                navigator.clipboard.writeText(use_text)
                    .then(
                        () => {
                            success_event_curse()
                        },
                        () => {
                            failed_event_curse()
                        }
                    )
            }))
        }
    }

然后发现无论按下什么按钮,复制出来的文本都是text[text.length - 1

#2

我认为是深浅拷贝的问题,于是将代码换成了这样子

export function JSON_DeepCopy(obj: Array<any> | string | number) {
    return JSON.parse(JSON.stringify(obj))
}

    export function ClipboardCopyByClass(class_id: string, text: Array<string>, success_event_curse: CallableFunction = (function () { }), failed_event_curse: CallableFunction = (function () { console.log('Clipboard Write Failed.') })) {
        var elements = document.getElementsByClassName(class_id)
        for (var i = 0; i < elements.length; i++) {
            var element = elements.item(i) as HTMLElement
            element.addEventListener('click', (function () {
                navigator.clipboard.writeText(i < text.length ? text[i] : text[text.length - 1])
                    .then(
                        () => {
                            success_event_curse()
                        },
                        () => {
                            failed_event_curse()
                        }
                    )
            }))
        }
    }

问题依旧存在

#3

「会不会是作用域的问题?」

    export class CBCopy {
        text_array: Array<string>
        constructor(text_array: Array<string>) {
            this.text_array = JSON_DeepCopy(text_array)
        }
        add_copy(
            element_class: string,
            success_event_curse: CallableFunction = (function () { }),
            failed_event_curse: CallableFunction = (function () { console.log('Clipboard Write Failed.') })
        ) {
            var element_collection = document.getElementsByClassName(element_class)
            for (var i = 0; i < element_collection.length; i++) {
                let element = <HTMLElement>element_collection[i]
                element.onclick = (() => {
                    let p = this.text_array[i]
                    navigator.clipboard.writeText(p)
                        .then(
                            () => {
                                console.log(p)
                                success_event_curse()
                            },
                            () => {
                                failed_event_curse()
                            }
                        )
                })
            }
        }
    }

然后...复制了一堆undefined...


所以

  • 这三份代码的问题各自出在哪里?
  • 又应该如何正确地使每一个按钮都能够复制出正确的文本呢?
    谢谢。(两个问题解决采纳)
  • 写回答

2条回答 默认 最新

  • 阿里嘎多学长 2024-06-10 13:08
    关注

    以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:


    从你的描述和代码尝试来看,问题主要出在闭包和作用域上。在JavaScript和TypeScript中,闭包允许函数访问创建时的作用域链,即使这个函数在那个作用域之外被执行。在事件监听器中,如果没有正确地使用闭包,可能会导致变量捕获错误,从而导致问题。

    问题分析

    1. 问题 #1:所有按钮复制的文本都是数组中的最后一个元素。

      • 原因:在事件监听器的回调函数中,use_text 变量在所有循环结束后都被设置为 text[text.length - 1]。这是因为回调函数捕获了 itext 的引用,而 i 在循环结束后变为 text.length
    2. 问题 #2:尝试使用深拷贝,但问题依旧存在。

      • 原因:深拷贝并不是问题所在。问题在于闭包没有正确捕获 text 数组中的元素。
    3. 问题 #3:复制的文本值是 undefined

      • 原因:在构造函数中使用 JSON_DeepCopy 并没有解决问题,因为闭包仍然没有正确捕获 this.text_array[i]

    正确实现

    要解决这个问题,我们需要确保每个事件监听器的回调函数都能捕获到正确的文本值。这可以通过使用立即执行函数表达式(IIFE)来创建一个新的作用域,并在其中捕获正确的值。

    export function ClipboardCopyByClass(class_id: string, text: Array<string>, success_event_curse: CallableFunction = () => {}, failed_event_curse: CallableFunction = () => { console.log('Clipboard Write Failed.') }) {
        var elements = document.getElementsByClassName(class_id);
        for (var i = 0; i < elements.length; i++) {
            var element = elements.item(i) as HTMLElement;
            element.addEventListener('click', (() => {
                let use_text = text[i]; // 捕获当前循环的文本值
                return () => {
                    navigator.clipboard.writeText(use_text)
                        .then(
                            () => success_event_curse(),
                            () => failed_event_curse()
                        );
                }
            })());
        }
    }
    

    解释

    • 我们使用了一个立即执行函数表达式 (() => {})(); 来创建一个新的作用域。
    • 在这个新的作用域中,我们通过 let use_text = text[i]; 捕获了当前循环的 i 和对应的 text[i]
    • 然后返回一个函数,这个函数将在事件触发时执行,并且能够访问到正确的 use_text

    参考资料

    通过这种方式,你可以确保每个复制按钮都能正确地复制其对应的文本值。希望这能帮助你解决问题!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 6月18日
  • 已采纳回答 6月10日
  • 创建了问题 6月10日

悬赏问题

  • ¥15 100 内验证哥德巴赫巴赫猜想
  • ¥15 需要在vitis下实现彩调视频图像累加,并输出
  • ¥15 解决不了的LNK2019错误
  • ¥20 MATLAB仿真三相桥式全控整流电路
  • ¥15 EDA技术关于时序电路设计
  • ¥15 百度文心一言流式返回sse失败
  • ¥15 由于远程方已关闭传输流,身份验证失败
  • ¥15 rt-detr,PCB,目标检测
  • ¥15 有偿求指导实证代码。cfps清洗合并后,无论是构建平衡面板还是非平衡面板,都是只剩几百个样本量。求指导一下哪里出问题了,不要潦草回复
  • ¥15 mutlinichenet