jQuery .val()方法不能设置<select>标签的值

5

我想知道为什么在调用replaceWith之后,jQuery的.val()函数不能设置<select>控件的值,但其他情况下它是有效的。

点击此处查看(不)起作用的示例

<select><option>ABC</option><option>DEF</option></select>
<input type="button" onclick="ControlOff()" value="Turn Off Control" />
<input type="button" onclick="ControlOn()" value="Turn On Control" />
<input type="button" onclick="Test()" value="Value Setting Test" /> 
function ControlOff() {
    $('select').each(function () {
        $(this).replaceWith('<span class="select-type">' + $(this).val() + '</span>');
    });
}

function ControlOn() {
    $('.select-type').each(function () {
        var selected = $(this).text();
        $(this).replaceWith('<select><option>ABC</option><option>DEF</option></select>');
        $(this).val(selected);
    });
}

function Test() {
    $('select').val('DEF');
}

2
这样只是将人们引用到我的jsFiddle问题中,可以吗? - 不仅可以,而且超级棒! - Jamiec
3
在Chrome中对我有效。我相信你会想设置option选项的value参数,就像 <option value='abc'>abc</option>那样。 - Dutchie432
在设置值时加1。此外,它在FF15.0.1中也可以正常工作。 - Jeff Watkins
不行。它在我最新的FF和最新的Chrome上无法工作。尝试将下拉菜单设置为DEF,然后单击Control Off,再单击Control On。虽然这应该将选择设置为DEF,但实际上并没有。 - user1589188
它对我也有效(Chrome 22)。 - Hugo Mota
为什么要替换?只需显示和隐藏该物件即可。 - epascarello
5个回答

2
问题在于,在 $(this).val(selected) 中的 $(this) 指向已经被移除的 <span> 元素,而不是你的新元素。你需要将其替换为:
$('select').val(selected);

要获取先前插入的元素。

另外,你的代码过于复杂,以下代码可以实现同样的功能,但更加简单:

function ControlOn() {
    $selectText = $('.select-type');
    var selected = $selectText.text();
    $selectText.replaceWith('<select><option>ABC</option><option>DEF</option></select>');
    $('select').val(selected); // Use an id instead to match: #my-select-id
}

请务必给<select>元素添加一个ID,否则一旦在页面上引入新的<select>元素,它就会出现问题。 点击此处查看工作示例。

感谢您的输入并点赞指出 $(this) 在调用 replaceWith 后未更新为新控件。但是我的代码并不复杂,我之所以这样做是因为有不止一个 <select>。因此,再次说明,您的代码并不适用于不止一个 <select>,而仅适用于单个 <select> - user1589188
@user1589188 当然,但你从未提到过有多个。但如果有的话,你会更改所有 <select> ;) 请提供更多上下文(在您的原始问题中),以便我可以更好地在我的代码中反映您的情况。 - phant0m
那和我的代码无关。就像我说的,我的代码是通用的,可以处理多个<select>。只需在HTML中添加更多的<select>,不要改变我的代码,你会发现我的代码对它们都有效。我只是从HTML部分删除了多个<select>,只是为了让示例更简洁。但还是谢谢你的建议。 - user1589188
@user1589188 我理解你的意思。我的意思是,问题中没有明确说明这一点,因此你必须预料到有些人会向你指出这种简化方法。这只是为了以后提问时给你的建议 ;) - phant0m
是的,我明白你的意思。下次我会尝试进一步简化我的代码或者更清晰地表述它。这次我直接复制了我的代码,因为我担心自己可能在代码方面犯了错误。 - user1589188

1
问题在于,在ControlOn中,你有一个each循环遍历.select-type元素,这些元素是span,而span不能使用val方法进行设置:

你可以通过将方法更改为以下内容来解决此问题:

function ControlOn() {
    $('.select-type').each(function () {
        var selected = $(this).text();
        var $select = $('<select><option>ABC</option><option>DEF</option></select>');
        $(this).replaceWith($select)
        $select.val(selected);
    });
}

实时示例:http://jsfiddle.net/qSYYc/4/


这个方法可以工作,但是我只设置了$(this),并没有设置所有的<select>。当我有多个不同值的<select>时,我不能使用你的代码。我的问题是$(this)已经被<select>替换了,那么$(this)现在不就是<select>吗?当然,<select>有val需要设置。 - user1589188
@user1589188 - 我完全理解你的观点,是我的错,因为你在示例的其他地方使用了较广泛的 $('select') 选择器。我会再看一遍。 - Jamiec
非常感谢!就是这样做!所以,在调用 replaceWith 后,$(this) 没有被更新是真的。很奇怪!你会发现,即使在调用 replaceWith 后,如果你调用 alert($(this).text()),你仍然会得到 span 中的文本!!! - user1589188

1

设置选项的值将解决您的问题。jsfiddle

<select><option value='ABC'>ABC</option><option value="DEF">DEF</option></select>

不是这样的。尝试将下拉菜单设置为DEF,然后单击“控制关闭”,再单击“控制打开”。你没有看到下拉菜单选择DEF吗? - user1589188
如果省略了“value”属性,则此内容无关紧要,因为该值会从文本继承。 - Jamiec
@Jamiec 如果值和文本不同怎么办?在这种情况下,你的建议会失败。 - Anoop
但是,在 OP 的问题中,它们是相同的。 - Jamiec

1
function ControlOn() {
    $('.select-type').each(function () {
        var selected = $(this).text();
        $(this).replaceWith($('<select><option>ABC</option><option>DEF</option></select>').val(selected));
    });
}

将您的代码重写成上述方式,它就可以工作了!

this 引用的元素不会改变为您刚创建的选择元素,它始终是该函数范围内的 span 元素。因此,您应该将值设置为新创建的 select,而不是不变的 $(this)


是的,我刚意识到这一点。但对我来说这很奇怪。$(this) 什么时候会更新???我想知道在 replaceWith 后面发生了什么。 - user1589188
this 是对绑定函数的对象的引用,由于其特性,它永远不会被重新分配。如果您熟悉Java/C++,您就会理解这个原理。 - Need4Steed

-1
我建议您使用“disabled”属性来打开和关闭选择,这样不会影响.val()功能。
function ControlOff() {
    $("select").attr("disabled", "disabled");
}

function ControlOn() {
    $("select").removeAttr("disabled");
}

谢谢,但这不是我想要实现的。 - user1589188
你想要实现什么?因为在<select>标签中嵌套<span>标签有点荒谬(只能包含<option>和<optgroup>标签http://www.w3.org/TR/html401/interact/forms.html#h-17.6),并且在不同的浏览器上可能会表现不同。 - Maddog
不,我使用replaceWith将<select>替换为<span>,而不是在<select>内添加<span> - user1589188
抱歉,我的错。我可能有点累了或者什么的 :-). - Maddog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接