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. 父元素本身不能是参数指定的元素(即排除自身作为子元素的情况)。

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结构可能产生性能损耗。优化策略包括:

  1. 缩小初始选择范围
    // 优先缩小搜索范围,避免遍历全页面  
    $("#main-content .section").has(".active")...  
    
  2. 缓存中间结果
    const $sections = $(".section");  
    const $filtered = $sections.has(".highlight");  
    
  3. 避免重复调用:将结果存储为变量供后续操作复用。

四、常见误区与解决方案

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() 方法的关键价值

通过本文的系统讲解,开发者应能理解以下核心要点:

  1. has() 方法的本质是“反向筛选父元素”,其方向与 find() 相反;
  2. 应用场景覆盖表单验证、动态内容过滤等高频需求,能显著提升代码简洁性;
  3. 结合其他方法与性能优化策略,可构建高效且健壮的DOM操作逻辑。

建议读者通过实际项目中的表单验证、内容过滤等场景,逐步深化对 has() 方法的理解。掌握这一工具后,DOM操作的复杂度将得到显著降低,代码可维护性也将随之提升。

最新发布