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

mac*_*ost 2 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
Run Code Online (Sandbox Code Playgroud)

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

// 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
Run Code Online (Sandbox Code Playgroud)

瞧,我的考试通过了.

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

$table.find('input[value="foo"]:first').val('bar');
Run Code Online (Sandbox Code Playgroud)

什么都不做,同时:

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

按预期工作?

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

mu *_*ort 5

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

<input id="t1">
<input id="t2">
Run Code Online (Sandbox Code Playgroud)

然后我们执行这个JavaScript:

$('#t1').val('pancakes');
$('#t2').attr('value', 'pancakes');
Run Code Online (Sandbox Code Playgroud)

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

<input id="t1">
<input id="t2" value="pancakes">
Run Code Online (Sandbox Code Playgroud)

所以使用val或多或少模拟你使用鼠标和键盘摆弄表单元素; 这些都不会改变底层元素.attr但是,调用会改变底层元素并#t2最终会产生一个真正的完整value属性(如果你想知道原因,请参阅adeneo的答案).

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

$('input[value=pancakes]').length
Run Code Online (Sandbox Code Playgroud)

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

问题不在于:

$table.find('input[value="foo"]:first').val('bar');
Run Code Online (Sandbox Code Playgroud)

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


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