【问题标题】:JavaScript/jQuery dropdownlist change event with closure not workingJavaScript/jQuery 下拉列表更改事件与关闭不起作用
【发布时间】:2012-01-06 01:42:43
【问题描述】:

在我的示例代码中,我有 2 个下拉列表(但在实际代码中,数字会有所不同,因为下拉列表是动态创建的)并且 我想要做的是计算有多少下拉列表被选择为非零值。我使用闭包来跟踪具有非零选定值的下拉列表的总数。我成功地做到了(参考http://jsfiddle.net/annelagang/scxNp/9/)。

旧/工作代码

$("select[id*='ComboBox']").each(          
          function() {              
              $(this).change(
                  function() {
                      compute(this);
              });         
      });

    var compute = (function () {
    var total = 11; 
    var selectedDdl = [];

    $("#total").text(total);     
    return function (ctrl) {
         var id = $(ctrl).attr("id");
         var ddlMeal = document.getElementById(id);
         var found = jQuery.inArray(id, selectedDdl);

        if (ddlMeal.options[ddlMeal.selectedIndex].value != 0){
             if(found == -1){
                 total += 1; 
                 selectedDdl.push(id);        
             } 
             else{
                 total = total;
             }
         }
         else {
             total -= 1;
             var valueToRemove = id;
             selectedDdl = $.grep(selectedDdl, function(val) 
                                      { return val != valueToRemove; });
         }        

         $("#total").text(total); 
    };     
}());

注意: 我用 11 初始化了总变量,因为正如我在实际代码中提到的,我可以有超过 2 个下拉列表,我只是想测试我的代码是否可以处理超过 2 的值.

当我尝试在 .change() 事件中传输闭包时,它不再起作用(请参阅http://jsfiddle.net/annelagang/scxNp/12/)有人可以帮我解决这个问题吗?我已经做这个代码几天了,它变得非常令人沮丧。

新的/无效的代码:

$("select[id*='ComboBox']").each(          
          function() {              
              $(this).change(
                  function() {
                     (function () {
                var total = 11; 
                var selectedDdl = [];

                $("#total").text(total);     
                return function (ctrl) {
                     var id = $(ctrl).attr("id");
                     var ddlMeal = document.getElementById(id);
                     var found = jQuery.inArray(id, selectedDdl);

                     if (ddlMeal.options[ddlMeal.selectedIndex].value != 0){
                         if(found == -1){
                             total += 1; 
                             selectedDdl.push(id);        
                         } 
                         else{
                             total = total;
                         }
                     }
                     else {
                         total -= 1;
                         var valueToRemove = id;
                         selectedDdl = $.grep(selectedDdl, function(val) 
                                           { return val != valueToRemove; });
                         }        
                    $("#total").text(total); 
                };     
        }());
          });         
      });

提前致谢。

附:我也愿意接受不那么混乱的解决方案。

【问题讨论】:

  • 在您的问题中发布相关代码会很有帮助。即使 jsfiddle 消失,它也能保持问题的相关性。
  • 添加了代码。感谢您的建议。

标签: javascript jquery closures


【解决方案1】:

问题

您正在从自执行匿名函数返回函数,但不要在任何地方赋值返回值。

简化您的代码,如下所示:

/* some code here */
$(this).click(function(){
    /** The following function is executed, returns result, but the
     *  result (a function) is not assigned to anything, nor returned
     */
    (function(){
        /* some code here */
        return function(ctrl){
            /* some code here */
        };
    }());
});
/* some code here */

解决方案

通常您的代码非常不可读,您应该为自己的利益改进它(并避免此类问题)。通过将参数传递给返回函数(但没有调用它)的函数,可以快速解决上述问题。解决方案在这里:jsfiddle.net/scxNp/13/

解决方案:解释

我所做的很简单 - 我发现您将 this 传递给第一个(工作)示例中的函数,但您甚至没有在第二个(不正确的)示例中执行此函数。简化后的解决方案如下所示:

/* some code here */
$(this).click(function(){
    /** Now the result of the following function is also executed, with
     *  parameter passed as in your working example
     */
    (function(){
        /* some code here */
        return function(ctrl){
            /* some code here */
        };
    }())(this);
});
/* some code here */

希望这是有道理的:)

附言。我还更新了我的第一个代码 sn-p,因此应该很容易发现更改:)

Ps.2。这只是一个 quickfix 并且 - 如上所述 - 要使您的代码具有可读性,还有很多工作要做。另外每个函数都作为闭包工作,所以不要过度使用你没有分配给任何东西的自执行(function(){/* your code */})();(它很有用,但一个脚本一次就足够了)。而是使用现有的闭包。

【讨论】:

  • 我按照你说的做了。它仍然没有工作。我在这里错过了什么吗? jsfiddle.net/annelagang/scxNp/14 谢谢。
  • 该解决方案只解决了一个问题。还有其他的。在新发布的小提琴中,每次发生变化时,它都会将总数重置为 11,然后仅根据更改的选择更新它,这意味着它只能显示 11 或 12。
  • @AnneLagang:詹姆斯可能是对的,它与您的示例不同(我的示例返回 10 或 12)。您能解释一下您对以下组合的期望吗?这是列表,请相应回答 (option1, option2): (0,0), (0,1), (0,2), (0,3), (1,0), (1,1) , (1,2), (1,3), (2,0), (2,1), (2,2), (2,3), (3,0), (3,1), ( 3,2), (3,3)
  • @Tadeck (0,0) = 11, (0,1) = 12, (0,2) = 12, (0,3) = 12, (1,0) = 12, (1,1) = 13, (1,2) = 13, (1,3) = 13, (2,0) = 12, (2,1) = 13, (2,2) = 13, (2 ,3) = 13, (3,0) = 12, (3,1) = 13, (3,2) = 13, (3,3) = 13...我不在乎选择的值是什么.假设初始计数为 11,我所追求的只是计算有多少非零选定值。无论如何,感谢您的冗长回答。当谈到闭包时,我是一个初学者。我一定会记住你的建议。谢谢!
  • @AnneLagang:没问题,我现在(在解释之后)看到,James 的方法在这里最适合你 :) 祝你好运!附言。考虑看看这个:O'Reilly: JavaScript Development and Resources - 非常好的起点!对于高级开发人员也很有价值 :) [这不是广告,我不隶属于 O'Reilly,我真的很喜欢他们的一些书]
【解决方案2】:

我相信这应该可行:

$("select[id*='ComboBox']").change(function() {
    $("#total").text($("select[id*='ComboBox'][value!=0]").length);
});

http://jsfiddle.net/scxNp/15/

【讨论】:

  • 您可能还想考虑在每个元素上放置一个共享类并在选择器中使用它而不是*=。有了你拥有的元素数量,它可能对性能无关紧要,但它看起来更干净。
  • 酷,简洁,直截了当。 :D 几个问题,长度是多少?如果我希望初始变量从 11 而不是 0 开始呢?
  • 基本上,它的作用是获取所有具有适当 id 且值不等于 0 的选择。然后 .length 告诉返回了多少元素。如果您想要某种偏移量,只需将其添加到 length jsfiddle.net/scxNp/17
  • 哦,我明白了。如果我知道存在这样的财产,我应该可以避免很多悲伤。谢谢! :D
【解决方案3】:

这个怎么样?

html:

<select id="ComboBox1" class="howMany">
<option value="0">Value 0</option>
<option value="1">Value 1</option>
<option value="2">Value 2</option>
<option value="3">Value 3</option>
</select>

<select id="ComboBox2" class="howMany">
<option value="0">Value 0</option>
<option value="1">Value 1</option>
<option value="2">Value 2</option>
<option value="3">Value 3</option>
</select>

<div id="total"></div>

脚本:

$(".howMany").change(
function ()
{
    var nonZero = 0;
    $(".howMany").each(
        function ()
        {
            if ($(this).val() != '0')
                ++nonZero;
        }           
    );
    $("#total").text('There are '+nonZero+' options selected');       
}
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 1970-01-01
    • 2016-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多