📕
余烬的小册
数据结构与算法GitHub
  • 总述
  • 经验记录
    • 经验总结
      • web component
      • 前端性能优化总结与分析
      • 我的长列表优化方案
      • 双向通讯解决方案
      • 🔧基于istanbul实现代码测试覆盖率工具
      • 表单系统(低代码表单)
      • 跨端小程序
      • 设计一个即时聊天功能
      • 跨页面通讯 3658699fe4cb4d0bbe22b0881390bacd
    • 踩坑记录
      • HTML踩坑记录
      • Flutter踩坑记录
      • CSS踩坑记录
  • 源码解析
    • Vue源码解析
      • Vue2源码解析系列-响应式原理
      • Vue2源码解析系列-模板编译
      • Vue2源码解析系列-渲染系统(待更新)
        • Patch
      • Vue2源码解析系列-调度系统(todo)
      • Vue2组件更新流程(todo)
      • 如何学习Vue源码
      • Vue3源码解析系列-响应系统
      • Vue3源码解析系列-渲染系统
      • Vue3源码解析系列-组件化和渲染优化(todo)
      • Vue router源码解析(todo)
    • React源码解析(todo)
    • 微前端
      • qiankun源码解析(todo)
    • Vite源码解析
      • Vite Client源码
      • Vite Server源码(todo)
  • 前端技术
    • javaScript
      • ES6
        • 变量声明
        • 模块化
        • 箭头函数
        • 你不知道的for...of
        • 新的数据结构Set和Map
        • JavaScript异步编程终极解决方案
        • ES6 Class 3a0c0a225a534984aabe9a943c5df975
      • JavaScript Error
      • JavaScript浅拷贝和深拷贝
      • JavaScript闭包
      • JavaScript最佳实践
      • JavaScript设计模式
      • async函数的polyfill
    • 深入理解JavaScript系列
      • JavaScript中的继承
      • JavaScript原始类型和引用类型
      • JavaScript浅拷贝和深拷贝
      • JavaScript手写系列
      • JavaScript之this
      • 词法环境和环境记录
      • JavaScript内存泄漏
      • 执行上下文
      • 从ECMAScript规范中学习this
    • TypeScript
      • TypeScript基础教程
      • Typescript高级操作
      • TypeScript工具类型
      • Typescript手写实现工具类型
      • Typescript总结(思维导图)
    • 浏览器原理
      • 页面渲染原理
      • 浏览器存储
      • JavaScript事件循环
      • 事件循环
      • 跨域
      • DOM事件流
      • 从输入url到页面渲染
      • 判断节点之间的关系及根据节点关系查找节点
      • history API
    • 跨端技术
      • Flutter
        • Flutter布局组件
    • 前端工程化
      • Babel插件开发指南
      • 循环依赖
      • pm2
    • React
      • React 状态管理
      • React组件通讯
      • Redux入门
      • Flux
      • React Hook(todo)
      • Effect
  • 服务器端
    • 计算机网络
      • 应用层
      • 运输层
      • 物理层
      • 数据链路层
      • HTTP缓存
      • HTTPS
      • 网络层
    • NodeJs
      • Node.js
      • nodejs最佳实践
      • 《深入浅出Nodejs》小结
      • mongoose填充(populate)
      • node事件循环
      • Node子进程
      • nestjs从零开始
      • nodejs流
      • Nodejs调试
      • Koa源码解析
    • 服务器
      • 操作系统
      • Linux
      • nginx常用指令
      • nginx常用配置
    • 数据库
      • Mysql常见语法
      • MongoDB Indexes索引
  • 前端安全与性能优化
    • 前端安全
      • 跨站脚本攻击(XSS)
      • 跨站点请求伪造(CSRF)
      • 点击劫持
      • 中间人攻击
      • 越权攻击与JWT
    • 前端性能优化
      • 前端监控系统
      • 前端性能优化总结与分析 7348bba0918645b1899006dc842a64c1
      • 衡量性能的核心指标 0dc15ef127cf4f4a9f1137c377420292
      • 图片懒加载
  • 杂项
    • 其他
      • Git
      • web component框架
      • 实现滚动框的懒加载
      • Stencil指南
    • CSS
      • 定位和层叠上下文
      • BFC
      • 盒模型
      • css选择器
      • css变量
由 GitBook 提供支持
在本页
  • 背景
  • 实现方案
  • Element.closest()
  • Node.contains()
  • **Node.**compareDocumentPosition
  • querySelector和querySelectorAll
在GitHub上编辑
  1. 前端技术
  2. 浏览器原理

判断节点之间的关系及根据节点关系查找节点

背景

在某些情况下,可能需要判断两节点间的关系,例如A节点是否是B节点的祖先节点,A、B节点是否是相邻兄弟节点,或者是根据已有的一个节点去寻找与其有某种关系的节点,例如寻找A节点的祖先节点中具有某className的节点。

实现方案

Element.closest()

Element.closest() 方法用来获取:匹配特定选择器且离当前元素最近的祖先元素(也可以是当前元素本身)。如果匹配不到,则返回 null。 需要注意的是,这种方法只对元素节点有效。

const targetElement = el.closest(selectors);

这种方法可以用于已知子孙元素节点和祖先节点的选择器,从而查找其祖先元素,或者判断当前元素节点是否有该祖先节点。

if(node.closest('div.isHidden')){
	// 如果node的某div祖先节点存在isHidden类名
}

Node.contains()

[Node](https://developer.mozilla.org/zh-CN/docs/Web/API/Node) 接口的 contains() 方法返回一个布尔值,表示一个节点是否是给定节点的后代,即该节点本身、其直接子节点(childNodes)、子节点的直接子节点等。

node.contains(otherNode)

这种方法适用于所有Node,不仅限于Element。

需要注意的是,contains 对自身节点调用也是true,即node.contains(node) === true // true 。

**Node.**compareDocumentPosition

如果上面的方法都不满足需求,那么可以使用compareDocumentPosition ,它能准确地比较两节点之间的具体关系,甚至可以比较不同文档(document)之间的节点。 compareMask = node.compareDocumentPosition( otherNode )

返回值是一个具有以下值的位掩码:

常量名
十进制值
含义

DOCUMENT_POSITION_DISCONNECTED

1

不在同一文档中

DOCUMENT_POSITION_PRECEDING

2

otherNode 在 node 之前

DOCUMENT_POSITION_FOLLOWING

4

otherNode 在 node 之后

DOCUMENT_POSITION_CONTAINS

8

otherNode 包含 node

DOCUMENT_POSITION_CONTAINED_BY

16

otherNode 被 node 包含

DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC

32

待定

需要特别注意的是,Node.compareDocumentPosition 返回的是位掩码,因此不能直接使用相等来判断,必须要按位与运算符才能得到正确的结果。

if(node.childNodes[0].compareDocumentPosition(node) & Node.DOCUMENT_POSITION_CONTAINS){
 // node包含node.childNodes[0]
}

这是因为有些情况下,节点之间可能存在多种关系,例如otherNode既包含node,又在文档中位于node的前面,那么返回值就是Node.DOCUMENT_POSITION_PRECEDING | Node.DOCUMENT_POSITION_CONTAINS ,也就是10 ,直接用相等符号判断得到的就将是无效的结果。

node.compareDocumentPosition(otherNode) === (Node.DOCUMENT_POSITION_PRECEDING | Node.DOCUMENT_POSITION_CONTAINS)

querySelector和querySelectorAll

querySelector API大家应该都很熟悉了,它与Element.closest API相反,主要用于查找子孙元素节点。

querySelector 返回与指定的选择器组匹配的元素的后代的第一个元素,而querySelector 返回所有匹配的子孙节点。

需要注意的是,querySelector方法同样也被定义在**Element**上,也就是说下面两种方法都是可以的:

document.querySelectorAll(selectors)
element.querySelectorAll(selectors)
上一页从输入url到页面渲染下一页history API

最后更新于1年前