jQuery 可以在coffeescript中遍历每个吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11371458/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 10:32:37  来源:igfitidea点击:

Possible to loop over each in coffeescript?

jqueryloopscoffeescript

提问by Tyler

I'm trying to programmatically create some javascript buttons to toggle visibility on the page (for snappy tag filtering). This works for one tag:

我正在尝试以编程方式创建一些 javascript 按钮来切换页面上的可见性(用于快速标记过滤)。这适用于一个标签:

trigger = ".sales-focus-btn"
target = ".sales-focus"

jQuery ->   
  $(trigger).toggle ->
    $("#primary-content").find('.container').hide()
    $("#primary-content").find(target).show()
  , ->
    $("#primary-content").find('.container').show()

Is it possible to do something similar in coffeescript, but with arrays, e.g.

是否可以在咖啡脚本中做类似的事情,但使用数组,例如

trigger = [
  ".sales-focus-btn"
  ".service-focus-btn"
  ".other-focus-btn"
  ...
]
target = [
  ...
]

Is it possible to loop over and create a toggle for each type of tag?

是否可以循环并为每种类型的标签创建一个切换?

UPDATE

更新

Yes it's possible. Use the form:

是的,这是可能的。使用表格:

myFunction = (el) -> console.log el
myFunction elem for elem in array

回答by Ricardo Tomasi

Of course it's possible:

当然有可能:

content = $('#primary-content')
container = content.find('.container')

tags = [
    '.sales-focus'
    '.service-focus'
    '.other-focus'
]

$.each tags, (tag) ->
    target = content.find(tag)
    $(tag + "-btn").toggle ->
        container.hide()
        target.show()
    , ->
        container.show()

Remember to cache your DOM elements. Alternatively use for tag in tagsinstead of jQuery.each tags, (tag) -> ...:

记住缓存你的 DOM 元素。或者使用for tag in tags代替jQuery.each tags, (tag) -> ...

for tag in tags
    do ->
      target = content.find(tag)
      $(tag + "-btn").toggle ->
        container.hide()
        target.show()
      , ->
        container.show()

(the do ->IIFE is necessary to keep each targetin scope, as @epidemian pointed out)

(正如@epidemian 指出的那样,do ->IIFE 有必要将每个target范围都保留在范围内)

回答by epidemian

You can call togglein a loop, but you have to be aware of the weird JS scoping rules. Basically, if you generate a function inside a loop, like this:

您可以toggle循环调用,但您必须了解奇怪的 JS 范围规则。基本上,如果您在循环内生成一个函数,如下所示:

for n in [1, 2, 3]
  $(".btn-#{n}").click -> alert "you clicked #{n}"

You will notice that all the buttons print "you clicked 3" when pressed. That's because the the scope of the nvariable is not limited to the body of the loop, but to all the function that contains that loop. So, when the loop runs the value of nis changed it's final value is 3. As all the functions created inside the loop have a reference to that same variable n, they will all print 3 when executed after the loop has finished. In CoffeeScript, you can circumvent this issue using a do statement, which will basically introduces new block-scoped variables:

您会注意到,所有按钮在按下 时都会打印“您点击了 3”。这是因为n变量的作用域不仅限于循环体,还包括包含该循环的所有函数。所以,当循环运行时, 的值n被改变,它的最终值是 3。因为在循环内创建的所有函数都有对同一个变量的引用n,它们在循环完成后执行时都会打印 3。在 CoffeeScript 中,你可以使用 a 来规避这个问题do statement,它基本上会引入新的块范围变量:

for n in [1, 2, 3]
  do (n) ->
    $(".btn-#{n}").click -> alert "you clicked #{n}"

Or using an auxiliary function:

或者使用辅助功能:

setupClick = (n) -> 
  $(".btn-#{n}").click -> alert "you clicked #{n}"

setupClick n for n in [1, 2, 3]

With that in mind, you could implement your loop like so (this is an adaptation of Ricardo's answer):

考虑到这一点,您可以像这样实现您的循环(这是对Ricardo's answer的改编):

$content = $('#primary-content')
$container = $content.find('.container')

targetsByTrigger =
  '.sales-focus-btn': '.sales-focus'
  '.service-focus-btn': '.service-focus'
  '.other-focus-btn': '.other-focus'

setupTrigger = (trigger, target) ->
  $(trigger).toggle ->
    $container.hide()
    $content.find(target).show()
    console.log 'showing', target
  , ->
    $container.show()

setupTrigger trigger, target for trigger, target of targetsByTrigger

Notice that i put both the triggers and targets class names in an object so the trigger class name can be from <target class name>-btn; if that's not the case, then sticking to an array like ['.sales-focus', '.service-focus', '.other-docus']and then adding -btnis probably better. Also, i like the convention of using $as a prefix for "jQuerized" values, but that's just personal preference :)

请注意,我将触发器和目标类名都放在一个对象中,因此触发器类名可以来自<target class name>-btn; 如果不是这种情况,那么坚持一个数组['.sales-focus', '.service-focus', '.other-docus'],然后添加-btn可能会更好。另外,我喜欢$用作“jQuerized”值前缀的约定,但这只是个人喜好:)