我以为我理解了整个道具与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
没有了真的改变了什么。这只会让我更加困惑。
答案 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()
是设置元素值的正确方法。