操作 HTML 元素的属性是前端开发里绕不开的基本功。jQuery 把这件事封装成了 attr() 方法,既能读取属性值,也能设置属性值,一个方法覆盖了属性操作的大部分需求。
跟原生 JavaScript 的 getAttribute() 和 setAttribute() 比起来,attr() 的调用链更流畅,而且处理了不少浏览器兼容性问题。不同浏览器对某些属性的返回值在历史上存在差异,jQuery 在底层做了统一化处理,省得开发者自己写一堆条件判断。
attr() 方法的四种调用形式
读取属性值:
$(selector).attr(attribute);
返回匹配元素中第一个元素的指定属性值。如果选择器啥也没匹配到,返回 undefined。
设置单个属性值:
$(selector).attr(attribute, value);
给所有匹配元素设置同一个属性和值。
用函数动态设置属性值:
$(selector).attr(attribute, function(index, currentvalue) {
return 新的属性值;
});
这个写法很灵活,函数接收两个参数——index 是元素在中的索引位置(从 0 开始),currentvalue 是该元素当前的这个属性值。函数返回什么,属性就设成什么。适合需要根据元素位置或原有值做差异化处理的场景。
批量设置多个属性:
$(selector).attr({
attribute1: value1,
attribute2: value2,
...
});
一次改多个属性,对象字面量的写法,键是属性名,值是对应的属性值。代码简洁,比链式调用多次 attr() 更清晰。
参数说明
attribute:要操作的属性名称,比如 "href"、"src"、"class"、"data-id" 等。
value:要设置的属性值,字符串类型。设 null 的话行为等效于 removeAttr(),会把该属性删掉。
function(index, currentvalue):回调函数方式设置属性值。index 从 0 开始计数,currentvalue 是当前元素的该属性现有值。返回值作为新属性值应用。
基础示例:用 attr() 动态修改图片尺寸
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$("img").attr("width", "500");
});
});
</script>
</head>
<body>
<img src="https://www.ebingou.cn/biancheng/images/1.jpg" alt="代码号学习编程配图" width="284" height="213">
<br>
<button>点击修改图片宽度为 500</button>
</body>
</html>
点击按钮后,图片的 width 属性从原来的 284 变成了 500。这个操作的本质是在 HTML 标签上直接改写了属性值。注意这里是改属性不是改 CSS 样式,如果 CSS 里也设了宽度且优先级更高,那属性值的变化在视觉上可能看不出来。
attr() 和 prop() 怎么选
写过 jQuery 的应该都遇到过这个问题:到底是该用 attr() 还是 prop()?
我自己的判断标准:HTML 标签上看得见的、写在标签里的固有属性,比如 href、src、title、alt、class、id,用 attr()。跟元素状态有关的动态属性,比如 checked、selected、disabled、readonly,用 prop()。
早期版本 jQuery 里 attr() 也能操作 checked 这类属性,但从 1.6 版本开始分工更明确了。我踩过一次坑:用 attr('checked', true) 设复选框状态,页面上看不出问题,但表单提交后后端收不到值。改成 prop('checked', true) 就正常了。所以现在处理表单元素的状态属性,一律用 prop()。
简而言之:静态标签属性走 attr(),动态状态属性走 prop()。记住这条能少掉很多头发。
进阶用法:用函数批量处理元素属性
这个例子展示函数式 attr() 的实际价值——给一组元素按索引设置不同的属性值:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#applyBtn").click(function(){
$(".codeLink").attr("title", function(index, oldValue) {
return "代码号编程链接第" + (index + 1) + "个,原title:" + oldValue;
});
});
});
</script>
</head>
<body>
<a class="codeLink" href="#" title="链接A">代码号教程入口一</a><br>
<a class="codeLink" href="#" title="链接B">代码号教程入口二</a><br>
<a class="codeLink" href="#" title="链接C">代码号教程入口三</a><br>
<button id="applyBtn">批量更新 title 属性</button>
</body>
</html>
三个链接点击按钮后,各自的 title 属性被按顺序重新赋值。函数里的 index 让每个元素拿到属于自己的序号,oldValue 把原来的 title 值也拼接进去。这种按索引差异化处理的需求,用函数方式比逐个选择元素再设置要方便得多。
批量设置多个属性
一次性给元素贴上好几个属性,对象写法干净利落:
$("a.external").attr({
href: "https://www.ebingou.cn/biancheng",
title: "访问代码号编程资源站",
target: "_blank",
rel: "noopener noreferrer"
});
四行变一行,可读性反而更好。这种写法在处理链接元素、表单元素初始化时很常用。
attr() 方法的两个主要优势
第一是使用便捷。attr() 直接挂在 jQuery 对象上调用,读属性时一行拿到值,设属性时可以继续链式调用其他 jQuery 方法,不用断链。原生写法得 document.querySelector('img').getAttribute('width'),链式调用时没法用,得拆成多步赋值给变量。
第二是跨浏览器一致性。不同浏览器对某些属性的返回值处理历史上不太一样,比如 href 属性在 IE 里返回绝对路径,其他浏览器返回写在 HTML 里的原始值。jQuery 的 attr() 对这些差异做了统一收敛,开发者拿到的值是可预期的。对于需要兼容多浏览器的项目,这项特性省了很多调试兼容性的时间。
attr() 操作自定义 data 属性的注意事项
HTML5 引入了 data-* 自定义属性,用 attr() 确实能读写它们:
// 读
$("#userCard").attr("data-user-id");
// 写
$("#userCard").attr("data-user-id", "1024");
但 jQuery 专门提供了 data() 方法来处理这类属性,底层有自动类型转换(字符串 "1024" 会转成数字 1024),而且数据存在内存里不直接操作 DOM,性能更好。对于 data-* 属性,日常读写建议用 data(),只在需要显式修改 HTML 标签上的属性值时用 attr()。
本节课程知识要点
attr() 不加 value 参数是读取,加 value 参数是设置,行为靠参数个数自动区分。读取时只返回第一个匹配元素的属性值,设置时对所有匹配元素生效。
用函数形式 attr(attribute, function) 可以实现按索引或按原值做差异化设置,比循环每个元素单独处理代码更精简。
处理 checked、selected、disabled 等布尔型状态属性用 prop(),不用 attr()。静态标签属性如 href、src、title、alt 用 attr()。
批量设置多个属性用对象写法 attr({key: value, ...}),一次性处理多个属性值,链式写法的良好替代方案。
attr() 读写的是 HTML 标签上的属性,跟 CSS 样式是两套体系。修改 attr('width') 不一定改变元素在页面上的实际宽度,这取决于 CSS 的优先级和盒模型计算。