试图理解为什么.attr('value','foo')有效但.val('foo')不

时间:2013-03-20 01:14:20

标签: jquery backbone.js

我以为我理解了整个道具与attr的关系,但我只是遇到了一个让我质疑这种理解的案例。

我正在编写一个生成表的Backbone View测试,我的测试基本上做了以下事情:

// assert that $table.find('input[value="foo"]').length == 2
$table.find('input[value="foo"]:first').val('bar');
// assert that $table.find('input[value="foo"]').length == 1

奇怪的是,第二个断言失败了。在经历了大量的撞击之后,我终于尝试了:

// assert that $table.find('input[value="foo"]').length == 2
$table.find('input[value="foo"]:first').attr('value', 'bar');
// assert that $table.find('input[value="foo"]').length == 1

瞧,我的考试通过了。

现在,我希望我可以发布所有相关代码的小提琴,但是有太多的方法(表单单独查看是685行),但我正在寻找一般理解类型的答案,而不是特定的“在你的代码中修复X“。而我想要了解的是,为什么会出现这样的情况:

$table.find('input[value="foo"]:first').val('bar');

什么都不做,而:

$table.find('input[value="foo"]:first').attr('value', 'bar');

按预期工作?

P.S。我不应该说.val('bar')什么也没做;如果之后我做了.val()它会显示值已经改变了......但是如果我检查了实际的元素,或者使用了新的选择器,或者类似的东西,那么很明显val没有了真的改变了什么。这只会让我更加困惑。

2 个答案:

答案 0 :(得分:5)

一个简单的例子应该对事物有所启发。假设我们从这个HTML开始:

<input id="t1">
<input id="t2">

然后我们执行这个JavaScript:

$('#t1').val('pancakes');
$('#t2').attr('value', 'pancakes');

视觉上,两个<input>看起来都一样,他们都会说pancakes。但是,如果你看一下底层的DOM元素,你会看到:

<input id="t1">
<input id="t2" value="pancakes">

所以使用val或多或少地模拟你使用鼠标和键盘摆弄表单元素;这些都不会改变底层元素。但是,调用attr会更改基础元素,而#t2最终将会显示真正的value属性(如果您想知道原因,请参阅adeneo's answer)。< / p>

为什么差异很重要?我注意到你正在使用属性选择器,所以快速查看它是值得的:

$('input[value=pancakes]').length

这将是1,因为<input>中只有一个甚至具有value属性,更不用说具有我们正在寻找的值的value

问题不在于:

$table.find('input[value="foo"]:first').val('bar');

没有做任何事情,问题是它没有做任何属性选择器可以看到的事情,因为val根本不对属性做任何事情。


上面的简单演示,打开你的控制台并看到有趣的东西:http://jsfiddle.net/ambiguous/PNtKk/

答案 1 :(得分:3)

val()直接更改属性,并且它不会在控制台中显示,而attr()会使用本机setAttribute()更改属性,以便在控制台中显示。

val()是设置元素值的正确方法。