jQuery val()无法设置selected属性 场景疑问与排查
嘿,让我们一步步拆解你遇到的这些问题,其实本质都是jQuery对DOM元素的处理逻辑和链式调用的特性导致的,我来给你详细解释清楚:
疑问1:为何示例1中仅第二个select选项的选中状态设置正确?
首先看你的代码逻辑:你先创建了一个select元素,给它设置了val("2"),然后调用.appendTo($('.td1'))——而页面上有两个.td1元素(对应表格里的两行)。
这里的关键是jQuery的.appendTo()处理多个目标时的行为:当你把一个未插入DOM的元素追加到多个目标时,jQuery会将原元素插入到第一个目标,然后对后续的每个目标克隆一个原元素的副本并插入。
但问题在于:你调用.val("2")时,是给原select元素设置了选中状态,但这个状态是保存在DOM元素的selectedIndex属性(property)里的,而jQuery默认的克隆操作只会复制元素的HTML属性(attribute),不会同步当前的DOM属性状态。
那为什么你看到第二个select的选中状态是对的?其实是因为原元素被插入到了最后一个.td1里(jQuery会按目标元素在页面中的顺序处理,最后一个目标得到的是原元素),而第一个.td1里的是克隆副本——副本没有继承原元素的selectedIndex属性,所以默认选中第一个选项;而原元素的选中状态是正确的,也就是你看到的第二个select。
疑问2:为何示例2中第一个select完全未渲染?
你的代码里连续调用了两次.appendTo():
.appendTo($('#td21')) .appendTo($('#td22'));
这里的核心逻辑是:当元素已经存在于DOM中时,.appendTo()会执行移动操作,而不是克隆。
第一次调用.appendTo($('#td21'))时,你创建的select被插入到了#td21里;第二次调用.appendTo($('#td22'))时,这个select已经在DOM里了,jQuery会把它从#td21中移除,然后插入到#td22里。所以最终#td21是空的,只有#td22里有这个select,自然也就只有它的选中状态是正确的。
关于val()方法的设计逻辑和正确用法
val()方法的设计逻辑很明确:
- 当调用在单个jQuery对象上时,它会设置/获取该DOM元素的value相关状态(对于select就是选中项);
- 当调用在包含多个元素的jQuery对象上时,它会遍历每个元素,分别设置它们的value状态。
你之前的用法问题主要出在时机和操作顺序上:
- 你先给单个未插入DOM的元素设置
val(),再把它(或它的副本)追加到多个目标——副本无法继承原元素的property状态; - 连续调用
.appendTo()会移动已在DOM中的元素,而不是克隆。
正确的写法参考
如果你要给多个目标创建带选中状态的select,推荐两种方式:
方式1:逐个创建并设置
先遍历每个目标元素,为每个目标单独创建select并设置选中状态:
$('.td1').each(function() { $('<select />') .append($('<option/>', { value: "1" }).text("first option")) .append($('<option/>', { value: "2" }).text("second option")) .append($('<option/>', { value: "3" }).text("third option")) .appendTo($(this)) .val("2"); });
这样每个select都是独立的,追加到DOM后直接设置val,确保每个都能正确生效。
方式2:克隆时同步状态
如果一定要先设置好状态再克隆,可以使用.clone(true)(true参数表示克隆元素的事件、数据以及DOM属性状态):
// 先创建并设置好选中状态的select var $select = $('<select />') .append($('<option/>', { value: "1" }).text("first option")) .append($('<option/>', { value: "2" }).text("second option")) .append($('<option/>', { value: "3" }).text("third option")) .val("2"); // 原元素插入第一个目标,克隆带状态的副本到第二个目标 $select.appendTo('.td1:first'); $select.clone(true).appendTo('.td1:last');
另外你提到的给option设置selected属性的方式,本质是通过HTML attribute来指定选中项,这种方式在克隆时会被复制(因为attribute是HTML结构的一部分),所以也能生效,但val()是jQuery官方推荐的更简洁的方式,只要选对时机就没问题。
内容的提问来源于stack exchange,提问作者Wojciech Górniak

