我遇到了一个奇怪的案例,据我所知,两件应该表现相同的事情表现得完全不同。
如果我在页面上有两个选择菜单,一个静态菜单在HTML中硬编码,一个在运行时使用JQuery附加到正文。然后我禁用两个选择菜单中的第一个选项。显示时,两个菜单的第一个选项都按预期禁用,但动态附加菜单会自动将值设置为第二个选项,而静态菜单仍然是第一个选中的。
http://jsfiddle.net/hm3xgkLg/1/
HTML:
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
使用Javascript:
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function() {
sel.append($("<option>").attr('value',this.val).text(this.text));
});
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
为什么这两个看似相同的选择菜单表现不同?我希望两者都像静态菜单一样(保持选择第一个值)是可能的吗?
还应该注意我尝试在$(document).ready中包装disable函数以排除菜单尚未呈现的问题,但没有任何更改。我还试过有两个不同的类,有两个单独的调用来禁用选项,以确保它没有以某种方式发生冲突而没有变化。
答案 0 :(得分:5)
为什么这两个看似相同的选择菜单会表现出来 不同
这是因为第一个select
已经是文档的一部分并被解析了。 As per the spec here:
初始状态选择了第一个选项..
因此第一个选项是预选的。稍后当您禁用一个选项时,它不会更改选择。
示例1 :您可以看到第一个select
已将disabled
属性应用于标记中的第一个选项。与第二个select
相比,第二个选项已预先选定。
<select class="dropMenu">
<option value="1" disabled>First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
&#13;
如果您使用Javascript动态添加select
,则会创建第二个select
并立即添加到body
。当它成为DOM的一部分时,没有选项,因此无法进行预选。稍后当你向它添加选项,然后禁用其中一个选项时,它似乎执行得太快,加载时第一个选项已被禁用,第二个选项被预先选中。
示例2 :请勿立即将select
附加到body
。填充options
后附加它。这一次,即使您稍后更改了option
属性,也会预先选择第一个disabled
。
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
sel.appendTo('body'); /* <--- append here */
$('.dropMenu option:nth-child(1)').prop('disabled', true);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
&#13;
示例3 :在disable
option
之前添加延迟。这将为您提供预先选择的第一个option
的预期行为,因为它将有足够的时间。
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
setTimeout(disable, 1000); /* <--- give some delay here */
function disable() {
$('.dropMenu option:nth-child(1)').prop('disabled', true);
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
&#13;
示例4 :您也可以在禁用它们之前明确选择一个option
。
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
$('.dropMenu option:nth-child(1)').prop('selected', true); /* <-- select explicitly */
$('.dropMenu option:nth-child(1)').prop('disabled', true);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
&#13;
答案 1 :(得分:1)
尝试在$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
中设置setInterval
,因为您正在创建动态下拉列表,因此执行和创建需要一些时间禁用下拉列表元素jquery将会运行执行。这个问题来了。
Checkout Code Snippet
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function() {
sel.append($("<option>").attr('value',this.val).text(this.text));
});
setTimeout(function() {
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
}, 1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
答案 2 :(得分:0)
默认情况下,如果您已为动态selected
的第一个选项添加了选项dropdown
,那么它就可以为您完成:
只需看到 DEMO :
$(arr).each(function(key,value) {
if(key==0)
sel.append($("<option>").attr('value',this.val).text(this.text).attr('selected',true));
else
sel.append($("<option>").attr('value',this.val).text(this.text));
});
现在为什么会这样?
对于静态select
,该元素已存在于DOM
中,然后您使用disabled
为第一个option
添加jquery
,默认情况下首先{ {1}}将保留为option
。
现在对于动态selected
,因为您要添加它select
可能是默认情况下不考虑dynamically
第一个select
,因为它已被禁用!!
即使我觉得这是一种奇怪的行为,但有时我们需要通过追踪和错误来处理这些事情。
答案 3 :(得分:0)
只需手动选择dinamically添加菜单中的第一个选项:
$('.dropMenu option:nth-child(1)')
.attr('disabled', 'disabled')
.attr('selected', 'selected');
jsfiddle here(我借用了你的:P): https://jsfiddle.net/z0dzk5nL/1/
修改强> 快速更新。 Here您可以找到&#34;选择&#34;的规范。元件。我引用了回答你问题的部分:
如果插入节点或删除节点,则会导致选项列表 获取或丢失一个或多个选项元素,或者选项元素 在选项列表中要求重置,然后,如果选择元素 多个属性不存在,用户代理必须先运行 以下列表中适用的一组步骤:
如果select元素的显示大小为1,并且没有选项元素 选择元素的选项列表的选择性设置为 true设置列表中第一个选项元素的选择性 树状排序中未被禁用的选项(如果有)为true。
如果select元素的选项列表中有两个或更多选项元素 将其选择性设置为true设置所有选择性 最后一个选项元素,其选择性在列表中设置为true 树顺序中的选项为false。
这里有一个小提琴,表明如果你在追加它时预先选择该选项,你可以在不丢失选择的情况下禁用(我使用for循环代替&#34;每个&#34; func完全证明):
jsfiddle.net/xnvbevhm/
(抱歉,我不能发布两个以上的链接,因为我没有足够的声誉:P)
答案 4 :(得分:0)
作为将第一个属性设置为选中的替代方法,使用具有最小时间(即1)的setTimeout似乎可以使事情按预期运行。不过,我仍在研究其原因。
setTimeout(function() {
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
}, 1);