【问题标题】:jQuery(formElement).val(null) : inconsistent results in different browsersjQuery(formElement).val(null) : 不同浏览器的结果不一致
【发布时间】:2014-08-22 10:53:01
【问题描述】:

代码在这里:

http://jsfiddle.net/jf7t2/1/

请在所有浏览器的最新版本上运行它,并亲自查看。单击按钮时,打开:

  1. 在 Chrome(当然还有 Safari)上,它只是不选择任何东西,而是创建了一些幽灵般的空选项
  2. 在 Firefox 和 Opera 上,它按我期望的方式工作,并希望它工作,取消选择所有选项
  3. 在 Internet Explorer 上,它什么也不做

那么,哪一个是预期的行为?

【问题讨论】:

  • 我认为这里要吸取的教训是,预期的行为并不重要,没有一个浏览器符合它们;)
  • 好点,但很难接受 :) 这是非常短的代码,可能会使生活变得更简单,我确信问题与 jQuery 相关,而不是与浏览器相关。
  • 更新:我很抱歉,我期望和想要的效果不是重置元素状态,而是取消选择所有选项。现在更新问题...

标签: javascript jquery cross-browser


【解决方案1】:

如果您查看 jQuery 1.5.1 源代码行 1970,您会看到:

// Treat null/undefined as ""; convert numbers to string
if ( val == null ) {
    val = "";

所以预期的行为与您将空字符串作为参数一样。

如果你继续到 1984 行,你会看到:

} else if ( jQuery.nodeName( this, "select" ) ) {
  var values = jQuery.makeArray(val);

  jQuery( "option", this ).each(function() {
    this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
  });
  if ( !values.length ) {
   this.selectedIndex = -1;
  }

所以预期的行为是:

  1. 如果有一个空字符串值的option,选择它。
  2. 如果没有设置selectedIndex = -1

从这里开始,如果 selectedIndex 设置为 -1,则由浏览器决定如何处理

看着msdn library 它说:

selectedIndex 属性返回 -1 如果选择对象不包含 任何选定的项目。设置 selectedIndex 属性清除任何 现有的选定项目。

所以在 ie 中,预期的行为似乎是它将取​​消选择所有选项

MDC documentation 和 firefox 也是如此,他们对此非常明确

返回当前的索引 选定的项目。您可以选择一个项目 通过将其索引分配给这个 财产。通过为此分配-1 财产,所有项目将 已取消选择。

似乎基于 webkit 的浏览器对事物有不同的看法。

如果你用谷歌搜索“webkit selectedIndex”,你会看到很多关于 select 标签的错误报告,所以也许它只是很时髦;)

想一想,这是 jQuery 中的一个错误,因为它是一个应该能够在不同浏览器中表现相同的库 - 应该报告 ;)

【讨论】:

  • 附录:总之,IE不遵循自己的规则?我的意思是,正如我们所看到的,它显然不会取消选择所有选项...
  • 嗯......是和否 - msdn 库只告诉我们,如果没有选择任何内容,它将返回 -1,而不是将其设置为 -1 会做什么......这似乎合乎逻辑会取消选择它,但是,什么时候 ie 甚至表现得合乎逻辑? ;) 但同样,jQuery 是一个跨浏览器库,应该能够处理这个问题,所以它在所有浏览器中的工作方式都是一样的,显然这还没有经过足够好的测试,你应该提交一个错误报告。
  • 再次感谢 Martin... 我在 jQuery 论坛上发布了这个问题,也许他们会提出一些更果断的解决方案。将 null 分配给 SELECT 将是取消选择其选定选项的非常有用的快捷方式。
【解决方案2】:

哪一个是预期的行为?

jQuery 的val() 函数是documented 来获取字符串值或字符串值数组,因此没有定义的行为。

尝试val([]) 不选择任何内容,或者使用defaultSelected 属性恢复原始值:

$('#select option').each(function() {
    this.selected= this.defaultSelected;
});

【讨论】:

  • 如果您阅读源代码,实际上有一个非常明确的行为,无论它是否记录在案。
  • @Martin - 我同意...我也在几个开发者博客中读到过这个(分配 null)。
【解决方案3】:

我用一个我认为可以帮助你的 jsfiddle 分叉了你的 jsfiddle: http://jsfiddle.net/marcosfromero/AYLrT/

我在 IE、Firefox 和 Chrome 中测试过

jQuery("#button").click(function(event){
    var select = jQuery("#select");
    // Button click will try to find a "none" option (with no value)
    if(select.find('option.none').length===0) {
        // If it's not found, it creates the option
        select.prepend('<option value="" class="none"></option>');   
    }
    // And then it selects it
    select.val('');
});

// When select value is changed...
jQuery('#select').change(function() {
    var me = $(this);
    // ... to something different than empty ("")...
    if(me.val() !== '') {
        //... it removes that option
        me.find('option.none').remove();   
    }
});

【讨论】:

  • 感谢您的努力,但我不是在寻找任何问题的解决方案 :) 我只是在质疑浏览器的行为,以防我错过了什么。
【解决方案4】:

这些行为都不是不合理的。 在 Chrome 中,这是有道理的,因为您将值设置为空,因此它什么也不显示。 在 IE 中,这是有道理的,因为您没有更改为有效值,因此它不会改变任何内容。

如果您希望所有浏览器的行为都像 Firefox,只需将值设置为 1。

【讨论】:

  • 问题是这些值是不可预测的/动态的。而且我不想通过让代码更复杂/更慢来使代码更脏......
  • 另外:Chrome 的行为没有意义,因为它不应该为 SELECT 元素引入新选项。 IE,不过我能理解。 Firefox 的直观行为当然是合理的 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-17
  • 2019-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多