【问题标题】:jQuery cannot change a value where JS can because the library is out of datejQuery 无法更改 JS 可以更改的值,因为该库已过时
【发布时间】:2011-08-15 16:12:30
【问题描述】:

简单回答:

我的代码库使用的 jQuery 库已过期。

如果您是最新的,请尝试以下操作:

  1. 通过未缩小版本的 jQuery 查看问题是否在库中(10 次中有 9 次可能不会)

  2. 当一切都失败时,只需编写一个纯javascript解决方案。


有时,当我使用 jQuery 在 javscript 中编写“类”时,jQuery 将无法正常运行。例如,今天我在输入选择上执行以下操作:

$(this).val(newValue);

这在 jFiddle 中工作得很好,但在我的项目中不起作用(两者都有 0 个脚本错误)。我试图尽可能地隔离代码,但无济于事,我无法让它工作。

对此的“解决方案”是直接编写 javascript 来设置值,它工作得很好。

我不是 jQuery 大师,但这不是我第一次在 jQuery“失败”时编写直接的 javascript 解决方案。有没有 jQuery 大师知道为什么会发生这样的事情?有没有一种我不知道的调试 jQuery 的方法?有没有其他人在使用 jQuery 时遇到过这些类型的问题?如果有,你有解决办法吗?


更新

2011 年 8 月 25 日

我下载了最新版本的 jQuery 库并逐步浏览它,但发现该错误可能已在 jQuery 1.4.4 和 1.6.2 之间解决。我没有意识到处理大部分 javascript 的人并没有让 jQuery 库保持最新。在逐步浏览 jQuery 1.4.4 库后,似乎 jQuery 出于某种原因无法找到我的选择器,因此从未设置该值。这个问题已经在1.6.2中解决了......

本周课程... 让您的 jQuery 库保持最新状态,并在事情不匹配时验证您的高级开发人员的声明。

-

我选择了我所做的答案,因为它是唯一真正帮助我诊断问题根源的答案。虽然单步执行未缩小版的 jQuery 是一个非常简单的解决方案,但实际上我应该在发布这个问题之前就这样做。稍后我将发布我的发现,说明为什么它不起作用。


2011 年 8 月 24 日

我同意用户 Sohnee 的观点,即使用重复的“名称”并不是坏习惯,而且在某些地方您确实需要它。

我觉得很愚蠢,因为发布的代码已经错误了将近一周了。我已经更新了代码。我将 init 函数移至公共范围。


2011 年 8 月 22 日

虽然我对问题的核心在于重名感到部分满意,但我需要知道为什么重名不好?

我知道在处理输入/css/等时,您通常除了 ID 是唯一的,类来表示组。我认为没有关于名称的任何规则,但如果有人可以向我解释为什么重复名称是不好的做法,我会考虑这个问题的答案。


2011 年 8 月 16 日

至于目前的答案,我不认为这是一个冲突。 jQuery 工作得很好。绑定正在触发,导致在两个实现中调用函数。

问题线是

$(overrideSelector).each(
    function(){         
        $(this).val(newVal);
    }
);

例如,如果我在 .each() 中控制台输出 newVal,它的值将是让我们说“A”。
然后,如果我控制台注销$(this).val(),它将是“B”。然后运行$(this).val(newVal);。之后,如果我做一个$(this).val() 的控制台日志,它仍然是'B'。

在 cmets 中,有人提到我可能用错了 this 这个词。这两个都在 Chrome 的控制台上返回了 0 个 javascript 错误。我将给出以下代码 sn-p 是什么问题。我会写原来的,然后用javascript替换它。

我知道名字是一样的,但没关系。我正在处理的页面是一个巨大的表单,克隆的选择只是为了让用户不必滚动回表单的另一部分。

HTML:

<div id='overrideHolder'>
</div>

<select name='mySelect'>
    <option value='A'>A</option>
    <option value='B'>B</option>
</select>

jQuery(这工作):

var someClass = (function(){
    var overrideSelector = '[name="mySelect"]';
    ...

    return{
        init : function(){
            $(overrideSelector).clone().appendTo('#overrideHolder');
            $(overrideSelector).each(
                function(){
                    $(this).bind(
                                 'change', 
                                 {}, 
                                 function(){
                                        someClass.overrideTryAgain(this);
                                 }
                    );
                }
            );
        }

        overrideTryAgain : function(element){
            var newVal = $(element).val();

            $(overrideSelector).each(
                function(){         
                    $(this).val(newVal);
                }
            );

            ...
         },
         ...
    } 
})();

$(document).ready(function(){
    someClass.init();
}

Javascript(可行):

var someClass : (function(){
    var overrideSelector = '[name="mySelect"]';
    ...

    return{
        init : function(){
            $(overrideSelector).clone().appendTo('#overrideHolder');
            $(overrideSelector).each(
                function(){
                    $(this).bind(
                                 'change', 
                                 {}, 
                                 function(){
                                        someClass.overrideTryAgain(this);
                                 }
                    );
                }
            );
        }

        overrideTryAgain : function(element){
            // NOTE: Using javascript instead of jQuery because jQuery was not duplicating the selected value properly
            var newValue = $(element).get(0);
            newValue = newValue.selectedIndex;

            $(overrideSelector).each(
                function(){
                    var currentSelect = $(this).get(0);
                    currentSelect.options[newValue].selected = true;
                }
            );

            ...
        },
        ...
    }
})();

...

$(document).ready(function(){
    someClass.init();
}

【问题讨论】:

  • 发布一些不起作用的代码,人们可以帮助你。
  • 轶事:我已经编写了大量的 jQuery 和 javascript,并维护了一个基于 jQuery 的大型应用程序,只有当你遇到编码错误时才会停止工作。
  • 您可能错误地使用了 this 关键字。您能否向我们展示您尝试运行此代码的上下文?
  • 我同意 JamieC,它总是以一些编码错误而不是 jquery 结束
  • 我支持 JamieC 和 Joseph Silber 的 cmets

标签: php javascript jquery html


【解决方案1】:

我试图从您的代码中重现该问题,并且像其他人一样无法这样做。因此,似乎有一些外部因素在干扰:冲突,与标记有关的东西,但通常一些不明显的东西。

这听起来像是源代码步进的工作。对未缩小的 jQuery 运行此命令,并使用调试器(例如内置 Chrome 调试器或 Firebug)跟踪有问题的行,以查看 jQuery 内部发生了什么。这应该可以揭示出问题所在,无论是 jQuery 错误还是您自己的代码/标记中以前没有看到的问题。

【讨论】:

  • 所以我们都很想知道问题出在哪里:)
【解决方案2】:

您必须确保选择正确的元素。为此,您可以使用 Chrome console.log 查看您尝试设置值的 DOM 节点。

HTML 上的重复名称很糟糕,原因很简单。当一个表单被发送到服务器时,其中的输入元素被提交,通过一个以 DOM 名称为键的对象发送值。如果您有重复的名称,则该对象不会将值与唯一键绑定。您可以有不同形式的相同名称,这是允许的。

您可以查看 Form Controls (w3.org) 的 html 规范,以获取有关 Control Namesbehavior for checkboxes 的更多信息。

WebForms 应用程序的注意事项:整个页面都是一个表单,永远不要使用相同的名称...

【讨论】:

  • 你能提供一个链接来备份你的答案吗?不是我不相信你,我只是想得到一个答案,让任何人在未来毫无疑问地以这种方式克隆元素时,你必须更改名称。
【解决方案3】:

首先确保包含 jquery 库。然后尝试使用jQuery 对象而不是$ 一些库在其代码中使用$。也看看jQuery.noConflict()方法:

http://api.jquery.com/jQuery.noConflict/

【讨论】:

    【解决方案4】:

    如果目的只是在选择之间克隆和“同步”值,那么您的解决方案似乎有点过于复杂。首先,您可能不需要所有每个循环,因为 $(overrideSelector) 会自动为您执行此操作。无论如何,这里是您的代码的简化版本(如果我错过了您的代码应该做的目的,请告诉我)

    var someClass = new function() {
             var overrideSelector = '[name="mySelect"]';
    
            this.init = function() {
                $(overrideSelector).clone().appendTo('#overrideHolder');
    
                $(overrideSelector).live("change", function() {
    
    
                    $(overrideSelector).val($(this).val())
                })
            }
        }
        $(document).ready( function() {
            someClass.init();
        })
    

    【讨论】:

    • 我会在星期五检查这个自动密码,看看我能找到什么!感谢您的简化!
    • 我试过这段代码,结果是一样的。这绝对让我发疯。我有一个解决方案,但是 jQuery 代码中间的 JS 解决方案看起来很奇怪。
    【解决方案5】:

    关于更新,这对我来说似乎总是更可靠:

    $(overrideSelector).each(
        function(i, element){         
            $(element).val(newVal);
        }
    );
    

    【讨论】:

    • 虽然这可以正常工作,但这并不是我的代码绊倒的原因。感谢您的回答!
    【解决方案6】:

    我正在研究这个问题,但无法让它与您的代码一起使用,但我尝试自己实现它...

    这对你有用吗?

    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head>
        <title>Untitled Page</title>
    </head>
    <body>
    
        <div id='overrideHolder'>
        </div>
    
        <select name='mySelect'>
            <option value='A'>A</option>
            <option value='B'>B</option>
        </select>
        <input id="addSelect" type="button" value="Add select" />
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script type="text/javascript">
            (function ($) {
                var _constants = {
                    selector: 'select[name="mySelect"]'
                };
    
                var _methods = {
                    init: function () {
                        var $select = $(_constants.selector).live('change', function (e) {
                            var $this = $(this);
                            var val = $(this).val();
                            $(_constants.selector).not($this).val(val);
                        });
                        _methods.cloneSelect($select);
    
                        $('#addSelect').click(function (e) {
                            _methods.cloneSelect($(_constants.selector).eq(0));
                        });
                    },
                    cloneSelect: function ($select) {
                        $select.clone().appendTo('#overrideHolder');
                    }
                };
    
                //shorthand for $(document).ready
                $(function () {
                    _methods.init();
                });
            })(jQuery);
        </script>
    </body>
    </html>
    

    【讨论】:

      【解决方案7】:

      在更深层次上出了点问题。

      1. 你不能简单地克隆选择,你不应该有两个具有相同名称的元素
      2. 原件和克隆件分开处理,不需要监听原件上的变化或重置副本上的值
      3. 放弃 .each 调用,jQuery 已经在内部为您完成了这项工作
      4. $(element).get(0) === 元素。您将其放入然后取出。

      也就是说,您可以按照 Michal 的建议尝试一下:

      var mySelect = $(overrideSelector)
      var mySelectClone = mySelect.clone().appendTo('#holder')
      
      mySelectClone.bind('change', function(){
        addressValidation.overrideTryAgain(this)
      })
      
      ...
      
      overrideTryAgain : function(element){
        var newVal = $(element).val()
        mySelect.val(newVal)
      }
      

      另外,你比较过两个版本的输出吗?

      overrideTryAgain : function(element){
          var newVal = $(element).val()
          var newVal2 = element.options[element.selectedIndex].value
          console.log("jQuery: "+ newVal)
          console.log("DOM: "+ newVal2)
      
          $(overrideSelector).val(newVal);
          ...
      },
      

      如果您的选项值包含空字符串或其他虚假值(“0”等),那么您将受到伤害。

      【讨论】:

      • 我知道元素不应该有相同的 ID,但在这种情况下,让它们同名有什么害处?它们代表相同的数据。
      • @Ricardo - 非常好的观点。拥有多个元素可能会在某些浏览器中破坏他的脚本(还没有发生在我身上)。阅读有关 name 属性的信息表明,例如,发布一个包含多个同名元素的表单是不好的(前几天回答这个问题时甚至没有想到)tizag.com/htmlT/htmlattributes.php
      • 大多数服务器端语言都非常喜欢具有相同名称的多个表单元素。如果它们具有相同的名称,ASP.NET 会将它们转换为一个数组,如果您使用数组语法 name="myName[]",PHP 会这样做
      【解决方案8】:

      我看到重复的命名表单元素会导致问题,所以我会尝试消除这些问题。

      我还建议在这种情况下对val() 方法非常小心。它在您的代码中看起来不错,但是很容易盯着一些期望的代码,忘记val() 只返回第一个匹配元素的值(在 DOM 中)。

      我试图复制您的问题,但实际上并没有。您可以进行很多简化,这可能会揭示问题:

      • 使用change 而不是bind('change',{}
      • 消除each 调用
      • newVal 传递给您的overrideTryAgain 方法——而不是一个元素。该元素不是必需的,这将使测试/调试更容易。

            var selector = "[name=mySelect]";
            var holder = "#overrideHolder";
            ...
            $(selector).clone().appendTo(holder);
            ...
            $(selector).change(function () {
                overrideTryAgain($(this).val());
            });
        
            var overrideTryAgain = function (newVal) {
                $(selector).val(newVal);
            }
        

      【讨论】:

      • 与以下相同 - 我知道元素不应该具有相同的 ID,但在这种情况下,让它们具有相同的名称有什么害处?它们代表相同的数据。
      • 无害,只是潜在的混乱。 $(selector).val() 永远不会返回第二个的值。
      【解决方案9】:

      在不同的 HTML 输入标签中有重复的“名称”是不是很糟糕? - 如果是这种情况,那么单选按钮会很糟糕。

      jQuery 不能改变 JS 可以改变的值 NO

      您的问题不在您提供的代码范围内。 jQuery 在执行您的要求方面没有任何问题,如果没有 完整 代码,几乎不可能精确定位 - 效果非常好。

      此语句由以下小提琴 http://jsfiddle.net/EeQEN/ 支持,这只是对所提供代码的简化。

      var overrideSelector = '[name="mySelect"]';
      
      var overrideTryAgain = function(element) {
          var newVal = $(element).val();
          $(overrideSelector).each(function() {
              $(this).val(newVal);
          });
      };
      
      $(overrideSelector).clone().appendTo('#overrideHolder');
      
      $(overrideSelector).each(function() {
          $(this).bind('change', {}, function() {
              overrideTryAgain(this);
          });
      });
      

      我已经尝试了所有最新版本的 jQuery,除非它是特定浏览器的错误(您没有指定),否则我怀疑问题出在可变范围韭菜上。

      如果您不相信,请提供问题的功能示例,我相信可以确定确切的问题。

      一条建议以供将来参考,不要重新查询 DOM;缓存所有选定的元素,并且永远不要通过元素循环应用事件 - 使用委托并允许事件冒泡,它不仅会提高性能,还会使您的代码更易于维护。

      【讨论】:

      • 我已将问题缩小到此代码。问题的重点是找到遇到此问题或可以提供解决方法的建议的人。 “范围泄漏”是什么意思?
      • 这个问题不存在——至少 jQuery 不存在。如果您查看fiddle,您会发现 jQuery 执行良好,并且范围 leek 我的意思是该变量可能在逻辑上相互冲突。如果您可以提供问题的完整代码,那么我确信我可以在几分钟内将其隔离。
      • 我会发布数千行代码,以及我的部分数据库。那不是一个选择。如果您可以提供范围泄漏的示例,那将很有帮助。
      • 只是一个重现问题的例子——我住在新西兰,所以我可以解决你的问题,但我会在半小时后睡觉。
      • 您能否发布可执行的代码,如果您关注我的fiddle,您会发现 jQuery 工作正常。我不会说其中包含“...”的代码重现问题给我发送一个 不起作用fiddle 链接:)
      【解决方案10】:

      在许多表单元素上具有相同的 name 属性实际上是有效的,这实际上是一些表单元素的工作方式,例如单选按钮。这也是一些服务器端语言的设计方式,例如 php 中的数组样式命名name="country[]"

      使用重复名称并不是一个坏习惯——您只需要注意,当您通过名称获取元素时,您并不是在处理唯一的元素。事实上,document.getElementsByName("sharedName") 返回一个结果数组,即使您只有一个具有指定名称的元素。

      所以这不是一个不好的做法的问题,而是你的代码(或你正在使用的框架中包含的代码)是否理解这种非唯一性的问题。

      【讨论】:

      • 服务器端是PHP,所以我使用了数组样式'name'。这是我第一次为两个元素发布相同的名称(这将是重复的)。我很困惑为什么 jQuery 不能更改我的 javascript 可以在完全相同的位置的值。
      【解决方案11】:

      我认为您在实现jQuery Class 时可能会有一些运气。

      我将您使用的类放在 jsfiddle 中,即使这样它也遇到了一堆问题。括号并非处处闭合,然后您尝试在函数内部定义未链接在一起的方法。

      var someClass = function(){
      
       ...
      
      })();
      

      缺少“函数”左侧的括号,并尝试在结尾括号中放入 jQuery。

      var someClass = (function(){
      
       ...
      
      })(jQuery);
      

      除此之外,我认为您无法定义正常的“方法”

      init : function(){
      
      overrideTryAgain : function(element){
      

      就像那个父函数里面的那样。

      【讨论】:

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