jQuery has() 方法(长文讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
前言:jQuery has() 方法的概述与定位
在网页开发中,元素查询与操作是核心任务之一。jQuery has() 方法作为DOM遍历工具库中的重要成员,允许开发者通过子元素的存在性来筛选符合条件的父元素。它的应用场景覆盖表单验证、动态内容过滤、DOM结构校验等场景,尤其适合需要精准控制元素选择逻辑的复杂项目。
对于编程初学者而言,理解 has()
方法需要结合CSS选择器知识与DOM层级关系;而中级开发者则可通过其与 find()
、filter()
等方法的对比,掌握更高效的选择策略。本文将通过循序渐进的讲解,结合代码示例和实际案例,帮助读者全面掌握这一工具。
一、基础语法与核心逻辑
1.1 方法定义与参数说明
has()
方法的语法如下:
jQuery.has( selector )
jQuery.has( element )
jQuery.has( jQuery object )
该方法接受三种类型参数:
- CSS选择器字符串(如
".active"
) - DOM元素对象
- jQuery对象
其核心逻辑是:返回所有包含指定子元素的父元素。这里的“包含”关系需满足以下条件:
- 父元素必须直接或间接包含参数指定的子元素;
- 父元素本身不能是参数指定的元素(即排除自身作为子元素的情况)。
1.2 与 find()
方法的对比
常被混淆的 find()
和 has()
方法,其方向恰好相反:
| 方法名 | 操作方向 | 返回结果类型 |
|----------|-----------------|--------------------------|
| find()
| 从父元素向下查找子元素 | 符合条件的子元素集合 |
| has()
| 通过子元素筛选父元素 | 符合条件的父元素集合 |
形象比喻:
find()
好比“从家族谱系中寻找特定后代成员”;has()
则是“通过后代成员的存在性,反向确定其祖先身份”。
二、典型应用场景与代码示例
2.1 基础用法:根据子元素存在性筛选父元素
假设页面中有以下HTML结构:
<div class="container">
<p>有效内容</p>
<span class="required">*</span>
</div>
<div class="container">
<p>无效内容</p>
</div>
若需筛选出包含 .required
子元素的容器,代码如下:
$(".container").has(".required").css("border", "2px solid red");
执行后,只有第一个 .container
会被添加红色边框。
2.2 复杂查询:结合多层嵌套结构
当元素层级较深时,has()
可通过嵌套选择器穿透多层子元素:
// 筛选包含 <section> 标签且该标签内有 <img> 元素的 .content 容器
$(".content").has("section img").addClass("has-image");
此例中,只要 .content
的任意后代节点满足条件,父元素就会被选中。
三、进阶技巧与性能优化
3.1 与 filter()
方法的协同使用
has()
可与 filter()
联合实现复杂逻辑:
// 筛选同时包含 .title 和 .button 的 .card 元素
$(".card")
.filter(function() {
return $(this).has(".title").length > 0
&& $(this).has(".button").length > 0;
})
.addClass("valid-card");
此处通过回调函数逐个验证元素是否同时满足两个子元素存在条件。
3.2 性能考量与优化建议
has()
的底层实现依赖于 querySelectorAll
和递归遍历,对于大规模DOM结构可能产生性能损耗。优化策略包括:
- 缩小初始选择范围:
// 优先缩小搜索范围,避免遍历全页面 $("#main-content .section").has(".active")...
- 缓存中间结果:
const $sections = $(".section"); const $filtered = $sections.has(".highlight");
- 避免重复调用:将结果存储为变量供后续操作复用。
四、常见误区与解决方案
4.1 误用 has()
筛选子元素本身
// 错误示例:尝试通过 <div> 筛选其自身
$("div").has("div"); // 返回空集合
原因:has()
排除父元素自身作为子元素的情况。若需筛选包含特定子元素的父元素,需确保父元素与子元素属于不同层级。
4.2 动态内容加载后的延迟查询
若DOM元素是异步加载的(如AJAX请求后插入),需在元素就绪后再执行查询:
$.get("/data", function(response) {
$(response).has(".target").appendTo("#results");
});
五、实战案例:表单验证中的应用
5.1 场景描述
在表单提交前,需验证每个字段组是否包含必填项:
<form>
<div class="field-group">
<label>Name <span class="required">*</span></label>
<input type="text">
</div>
<div class="field-group">
<label>Age</label>
<input type="number">
</div>
</form>
5.2 代码实现
$("form").on("submit", function(e) {
e.preventDefault();
$(".field-group")
.has(".required") // 筛选有 * 的字段组
.each(function() {
const input = $(this).find("input");
if (input.val().trim() === "") {
input.css("border-color", "red");
}
});
});
此案例中,has()
精准定位需要验证的字段组,结合 .each()
实现逐项检查。
六、与其他方法的联动与扩展
6.1 与 not()
方法的组合
排除包含特定子元素的父元素:
$(".container").not(function() {
return $(this).has(".hidden").length > 0;
}).addClass("visible");
6.2 结合CSS伪类选择器
// 筛选包含至少一个 .item 元素且该元素为可见的容器
$(".list").has(".item:visible");
结论:掌握 has() 方法的关键价值
通过本文的系统讲解,开发者应能理解以下核心要点:
has()
方法的本质是“反向筛选父元素”,其方向与find()
相反;- 应用场景覆盖表单验证、动态内容过滤等高频需求,能显著提升代码简洁性;
- 结合其他方法与性能优化策略,可构建高效且健壮的DOM操作逻辑。
建议读者通过实际项目中的表单验证、内容过滤等场景,逐步深化对 has()
方法的理解。掌握这一工具后,DOM操作的复杂度将得到显著降低,代码可维护性也将随之提升。