的 .
我正在尝试为文档创建手风琴效果,当您单击
文档的其余部分(
)时带有向上和向下滑动的切换开关。然而我一直遇到问题。下面是代码:HTML
<article>
<h1>Title</h1>
<div class="container">
//...
</div>
</article>
<article>
//...
</article>
<article>
//...
</article>
CoffeeScript:
articles = $('article').toArray()
for article in articles
#console.log $('.container', article).parent().attr('id')
$('h1', article).click ->
$('.container', article).slideToggle 'slow'
当我使用 article
变量时... console.log
它会轮流浏览文章并打印回它们的 id。但是,当我点击任何
元素时,它总是会折叠最后一个
的 .
我认为这是因为 article
变量存储在 CoffeeScript 中 for
循环的范围之外,并且只有在循环完成后才会执行单击。
如果这是真的,如何保证在执行单击事件时引用正确的对象?使用 for i in [0...3]
循环并直接引用数组会更好吗?问题完全是别的吗?感谢您的帮助!
对于那些可能不熟悉 CoffeeScript 的人,这里是编译后的 javaScript(只需忽略 _results 变量):
var articles
articles = $('article').toArray();
_results = [];
for (_i = 0, _len = articles.length; _i < _len; _i++) {
article = articles[_i];
_results.push($('h1', article).click(function() {
return $('.container', article).slideToggle('slow');
}));
}
I'm attempting to create an accordion effect for a document where when you click on an <h1>
the rest of the document (the <div.container>
) with toggle sliding up and sliding down. I keep running into a problem however. Here is the code:
HTML
<article>
<h1>Title</h1>
<div class="container">
//...
</div>
</article>
<article>
//...
</article>
<article>
//...
</article>
CoffeeScript:
articles = $('article').toArray()
for article in articles
#console.log $('.container', article).parent().attr('id')
$('h1', article).click ->
$('.container', article).slideToggle 'slow'
When I use the article
variable in say... the console.log
It rotates through the articles and prints back their ids. But when I go to click any of the <h1>
elements, it always collapses the last <article>
s <div.container>
.
I think this is because the article
variable is stored outside of the scope of the for
loop in CoffeeScript and the click doesn't execute until after the loop has already completed.
If this is true, how do I guarantee that the right object is being referenced when the click event is executed? Would it be better just to use a for i in [0...3]
loop and just reference the array directly? Is the problem something else entirely? Thank you for your help!
For those who may not be familiar with coffeeScript, here's the javaScript that is compiled (just ignore the _results variable):
var articles
articles = $('article').toArray();
_results = [];
for (_i = 0, _len = articles.length; _i < _len; _i++) {
article = articles[_i];
_results.push($('h1', article).click(function() {
return $('.container', article).slideToggle('slow');
}));
}
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(4)
您看到此行为的原因是,在触发处理程序之前,不会评估
click
事件中引用的article
,并且在该时间点,它被设置为在您的循环中评估的最后一篇文章。这可能对你来说更好一些(抱歉,不确定咖啡脚本的实现):
The reason you are seeing this behavior is because the
article
referenced in theclick
events is not evaluated until the handler is triggered, and at that point in time, it is set to the last article which was evaluated in your loop.This may work a bit better for you (sorry, not sure of the coffee script implementation):
罗科的回答是正确的。让我扩展一下:
这是一个常见的混淆领域:只有函数在 JavaScript(和 CoffeeScript)中创建作用域,这意味着当您在循环中异步执行某些操作时,您必须记住“捕获”变量。在 CoffeeScript 中执行此操作的首选方法是使用
do
语法,它允许您将其编译为等效的
那种方式,每个
click
回调都会看到它自己的click
迭代。 code>article,而不是在循环过程中改变值的那个。我在 PragPub 文章 A CoffeeScript Intervention 中简要讨论了这一点。Rocco's answer is correct. Let me expand on it:
This is a common area of confusion: Only functions create scope in JavaScript (and CoffeeScript), which means that when you do something asynchronous within a loop, you have to remember to "capture" the variable. The preferred way to do that in CoffeeScript is with the
do
syntax, which lets you writewhich compiles to the equivalent of
That way, each
click
callback sees its own iteration ofarticle
, not the one that changes value as you go through the loop. I talk about this briefly in my PragPub article A CoffeeScript Intervention.这是另一种方法(在 javascript/jQuery 中):
this.parentNode
从单击中获取上下文.container 对象。
这样,我们不必在单击过程中存储任何状态,因为我们只需找到与单击的项目共享相同父级的容器。此方法也不依赖于容器对象相对于单击的 h1 的确切位置 - 它只需要容器共享相同的父级,以便在将来的布局中更加灵活。
Here's another way to do it (in javascript/jQuery) by:
this.parentNode
to get the context from the click.container
object under that common parent.This way, we don't have to store any state across the click as we can just find the container that shares the same parent with the item that is clicked on. This method also doesn't rely on the exact position of the container object relative to the h1 that is clicked on - it just needs the container to share the same parent so it's more flexible in future layout.
我对 Coffeescript 一无所知,但编译后的 Javascript 有一个非常明显的错误。
这一行:
应该这样读:
通过此更改,article 变量将被视为调用范围的一部分,并在调用处理程序时引用适当的元素(而不是引用隐式全局变量)。这就是修复错误所需的全部内容。
希望有一种方法可以在 Coffeescript 中指定这一点,但似乎非常可怕,对于文章中的文章 不会自动执行此操作。
I don't know anything about Coffeescript, but the compiled Javascript has a pretty obvious bug.
This line:
Should read like this:
With this change, the article variable will be considered part of the calling scope and reference the appropriate element when it comes time to call your handler (rather than referencing an implicit global variable). That's all you need to fix your bug.
Hopefully there's a way to specify that in Coffeescript, but it seems pretty horrendous that for article in articles doesn't do that automatically.