在单击动态创建的元素coffeescript时绑定Class方法

Bind a Class method on click of a dynamically created element coffeescript

本文关键字:绑定 Class 方法 coffeescript 元素 单击 动态 创建      更新时间:2023-09-26

我有一个类Text,用于处理从输入生成的文本,并使其可自定义。例如,我有一个基于给定颜色数组创建颜色按钮的类,代码如下:

<>之前给函数颜色数组的例子颜色:红色:" 255,0,0 "蓝色:"24,149,207"格林:"74、165、76"格雷:"202,202,202"黑色:"0,0,0"黄色:"183,118,4"白色:"255,255,255"紫色:"83,74,166"这个方法通过颜色循环,为每个颜色创建一个按钮,并绑定on click事件generateColorButtons: (colors) ->colorDiv = $('
',类:"colors")对于颜色,RGB的颜色Button = $("",类:颜色)# itemUniqueId在实例化时被赋予类按钮。在"click"上,@txtColor(@itemUniqueId, rgb)按钮。appendTo colorDiv返回colorDiv这是我在click上调用的方法txtColor: (id, color) ->$(" # " +身份证+ .addedTxt) . css"颜色","rgb("+颜色+")"之前

单击任何颜色按钮给我这个错误"Uncaught TypeError: undefined不是一个函数",我知道这是因为它不能访问它绑定的类方法,但是有一种方法可以使它工作,或者我必须将它声明为一个常规函数?

我只需要稍微改变一下点击绑定就可以了,下面是生成颜色的新类:

<>之前循环遍历选项中的每个颜色变量,为每个颜色变量创建一个按钮generateColorButtons: (colors) ->colorDiv = $('
',类:"colors")对于颜色,RGB的颜色Button = $('',类:颜色)#从'on'切换到'bind',并创建参数来保存rgb变量,因为我有范围问题,而不是直接调用txtColor函数,我创建了一个带有胖箭头的匿名函数,然后调用其中的txtColor。按钮。绑定'click', {param: rgb}, (event) =>@txtColor (@itemUniqueId event.data.param)按钮。appendTo colorDiv返回colorDiv

您已经弄清楚了这一点,但是让我解释一下哪里出了问题,以及为什么您(认为)在button.bind调用中需要{param: rgb}参数。

你的原始代码是这样写的:

button.on 'click', @txtColor(@itemUniqueId, rgb)

@txtColor(@itemUniqueId, rgb)是对txtColor方法的调用,当button.on的参数正在构建时发生,即当您调用button.on而不是点击发生时发生。这就相当于这样说:

x = @txtColor(@itemUniqueId, rgb)
button.on 'click', x

而这显然不是你想要做的。

最明显的解决方案(可能是您尝试的下一件事)是这样的:

button.on 'click', =>
    @txtColor(@itemUniqueId, rgb)

当你这样做时,你会发现任何点击8个按钮中的任何一个都将使用相同的RGB值,并且该RGB值将是for ... of循环迭代的最后一个。为什么会这样?当你有这样的东西:

for k, v of obj
    f = -> v
    ...

每个迭代器将创建一个新函数并将其留在f中,但是(这有点但是)这些函数在被调用之前都不会计算v的值。所有的函数在构建时都会做的就是存储对v的引用,v的值在每个迭代器上都会改变,但v仍然是相同的变量。结果是,当调用函数时,它们最终都将使用v的相同值,并且该值将是v在迭代中的最后一个值。

一个例子可能有用。如果你这样做:

fns = for i in [0, 1, 2]
    -> i
for f in fns
    console.log f()

那么你最终会在你的控制台上有三个2

这个问题在(Java|Coffee)Script中很常见,所以CoffeeScript有一个专门针对这种情况的解决方案(本节结束):

当使用JavaScript循环生成函数时,通常会插入闭包包装器,以确保循环变量被关闭,并且所有生成的函数不只是共享最终值。CoffeeScript提供了do关键字,它可以立即调用传递的函数,转发任何参数。

你可以使用do来重写你的循环,像这样:

for color, rgb of colors
    do (color, rgb) =>
        button = $('<button></button>', class: color)
        button.on 'click', =>
            @txtColor(@itemUniqueId, rgb)
        button.appendTo colorDiv

强制在计算do时计算rgb,这样您就不会遇到常见的引用问题。