前言
近期整理了一下 DOM 相关的操作函数,一行代码实现一个功能。涵盖了检测页面位置、获取同级元素、获取坐标、插入元素、查找元素、序列化表单等常见操作,可以在实际开发中大大提高代码的简洁性。
有人会说,你这种代码敢用在项目里?你猜会不会被同事骂死?
嘿嘿,那就教你一招,把本文每个功能函数所对应的代码详解,当成注释写上,这样不仅不会被骂,还会被夸牛*,我相信你会回来感谢我的!
以下每个函数均包含详细解释及使用示例,尽情享用吧!!!
tips:由于掘金代码展示区域显示一行代码,超出部分会被隐藏,所以提供了两个版本的代码,分别为可视版(方便查看完整代码)和可复制版(方便复制粘贴使用)。就问你们贴不贴心!
上菜
1、检查当前环境是否支持触摸事件
可视版
可复制版
const touchSupported = (): boolean => (
'ontouchstart' in window || (window as any)['DocumentTouch'] && document instanceof (window as any)['DocumentTouch']
);
代码详解
该函数的逻辑包含两个部分,分别用 ||
连接,只要其中一个条件为真,那么整个函数就返回 true
。
-
'ontouchstart' in window
: 使用in
关键字检查window
对象上是否有ontouchstart
属性。如果存在,说明当前环境支持触摸事件,这个条件为真。 -
(window as any)['DocumentTouch'] && document instanceof (window as any)['DocumentTouch']
: 这个条件包含两个子条件,用&&
连接,两个子条件都为真时,这个条件才为真。(window as any)['DocumentTouch']
: 使用类型断言(window as any)
将window
对象视为any
类型,然后检查其上是否有DocumentTouch
属性。如果存在,说明当前环境可能支持触摸事件。document instanceof (window as any)['DocumentTouch']
: 如果DocumentTouch
属性存在,那么继续检查document
是否是DocumentTouch
类型的实例。如果是,说明当前环境确实支持触摸事件,这个条件为真。
2、检查是否已滚动到页面底部
可视版
可复制版
const isAtBottom = (): boolean => document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight;
代码详解
这个函数用于判断当前页面是否已经滚动到底部。
函数逻辑包含一个条件,当条件为真时,说明页面已经滚动到底部。
以下是详细解释:
document.documentElement.clientHeight
: 获取文档根元素(<html>
)的可视区域高度。window.scrollY
: 获取当前窗口垂直滚动条的位置,即页面垂直方向上已滚动的像素值。document.documentElement.scrollHeight
: 获取文档根元素(<html>
)的完整高度,包括超出可视区域的部分。document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight
: 检查当前可视区域高度加上已滚动的像素值是否大于或等于文档的完整高度。如果是,则说明页面已经滚动到底部。
这个函数在处理页面滚动事件时特别有用,例如在用户滚动到底部时自动加载更多内容。
3、获取给定 DOM 元素的所有同级兄弟节点
可视版
可复制版
const siblings = (ele: Node): Node[] => (ele.parentNode ? [].slice.call(ele.parentNode.children).filter((child) => child !== ele) : []);
代码详解
该函数接受一个 Node
类型参数 ele
,返回一个 Node[]
类型的数组。这个函数用于获取给定 DOM 元素的所有同级兄弟节点。
以下是详细解释:
(ele: Node): Node[] =>
: 定义一个接受Node
类型参数ele
且返回类型为Node[]
的箭头函数。ele.parentNode
: 获取给定元素的父节点。如果存在,继续下一步;如果不存在(即ele
为根节点或不在文档树中),返回一个空数组[]
。[].slice.call(ele.parentNode.children)
: 使用Array.prototype.slice.call()
将类数组对象ele.parentNode.children
转换为数组。这里ele.parentNode.children
是包含父节点下所有直接子节点的类数组对象。.filter((child) => child !== ele)
: 使用filter
方法筛选出与给定元素ele
不同的子节点,即获取所有兄弟节点。ele.parentNode ? ... : []
: 使用三元条件运算符,当ele.parentNode
存在时返回筛选后的兄弟节点数组,否则返回一个空数组[]
。
使用示例
const targetElement = document.querySelector('#target');
const siblingNodes = siblings(targetElement);
console.log('Sibling nodes of the target element:', siblingNodes);
4、获取指定 DOM 元素的绝对坐标
可视版
可复制版
const getPosition = (ele) => ((r = ele.getBoundingClientRect()), { left: r.left + window.scrollX, top: r.top + window.scrollY });
代码详解
该函数接受一个参数 ele
(通常为一个 DOM 元素),返回一个包含两个属性 left
和 top
的对象。这个函数用于获取给定 DOM 元素相对于 document 的绝对坐标(即距离 document 左上角的横向和纵向像素值)。
以下是详细解释:
((r = ele.getBoundingClientRect()), ...
: 使用圆括号包含的逗号表达式,首先调用ele.getBoundingClientRect()
方法获取元素相对于视口的位置信息,该方法返回一个包含left
、top
等属性的对象。将此对象赋值给变量r
。{ left: r.left + window.scrollX, top: r.top + window.scrollY }
: 创建一个新对象,其属性left
和top
分别为元素相对于视口的横向和纵向坐标加上窗口的滚动距离(window.scrollX
和window.scrollY
)。这样就得到了元素相对于文档的绝对坐标。
使用示例
getPosition(document.body); // { left: 0, top: 0 }
5、将某个元素插入到指定元素之后
可视版
可复制版
const insertAfter = (ele: Element, anotherEle: Element): Element | null => anotherEle.insertAdjacentElement('afterend', ele);
代码详解
该函数接受两个参数 ele
和 anotherEle
(均为 Element
类型),返回一个 Element | null
类型的结果。这个函数用于将一个元素(ele
)插入到另一个元素(anotherEle
)之后。
以下是详细解释:
(ele: Element, anotherEle: Element): Element | null =>
: 定义一个接受两个Element
类型参数ele
和anotherEle
且返回类型为Element | null
的箭头函数。anotherEle.insertAdjacentElement('afterend', ele)
: 调用insertAdjacentElement
方法将ele
插入到anotherEle
之后。该方法接受两个参数:插入位置和要插入的元素。插入位置为'afterend'
,表示在目标元素anotherEle
之后插入。要插入的元素为ele
。
当插入成功时,insertAdjacentElement
方法返回插入的元素;如果插入失败(例如,anotherEle
不在文档树中),则返回 null
。
6、将某个元素替换为指定元素
可视版
可复制版
const replace = (ele: Element, newEle: Element): Element | null => (ele.parentNode ? ele.parentNode.replaceChild(newEle, ele) : null);
代码详解
该函数接受两个参数 ele
和 newEle
(均为 Element
类型),返回一个 Element | null
类型的结果。这个函数用于将一个元素(ele
)替换为另一个元素(newEle
)。
以下是详细解释:
-
(ele: Element, newEle: Element): Element | null =>
: 定义一个接受两个Element
类型参数ele
和newEle
且返回类型为Element | null
的箭头函数。 -
ele.parentNode ? ele.parentNode.replaceChild(newEle, ele) : null
: 使用三元条件运算符。如果ele.parentNode
存在,调用replaceChild
方法将ele
替换为newEle
;如果不存在(即ele
为根节点或不在文档树中),返回null
。ele.parentNode
: 获取给定元素ele
的父节点。ele.parentNode.replaceChild(newEle, ele)
: 调用replaceChild
方法,将给定元素ele
替换为新元素newEle
。此方法接受两个参数:新元素和要替换的元素。
当替换成功时,replaceChild
方法返回被替换的元素;如果替换失败(例如,ele
不在文档树中),则返回 null
。
7、将表单数据序列化为 JS 对象
可视版
可复制版
const serialize = (formEle) => Array.from(new FormData(formEle)).reduce((p, [k, v]) => Object.assign({}, p, { [k]: p[k] ? (Array.isArray(p[k]) ? p[k] : [p[k]]).concat(v) : v }), {});
代码详解
该函数接受一个参数 formEle
(通常为一个表单元素),返回一个对象。这个函数用于将表单元素的数据序列化为一个 JavaScript 对象,其中键为表单元素的 name
属性,值为表单元素的值。
以下是详细解释:
-
Array.from(new FormData(formEle))
: 使用FormData
构造函数获取formEle
中的表单数据,然后使用Array.from()
将其转换为数组。数组的每个元素是一个包含两个元素(键值对)的数组,表示表单元素的name
属性和值。 -
reduce((p, [k, v]) => ..., {})
: 使用reduce
方法将键值对数组转换为一个对象。reduce
方法接受一个回调函数和一个初始值(这里为空对象{}
)。- 回调函数的第一个参数
p
是累积器,用于保存已处理的键值对。 - 回调函数的第二个参数
[k, v]
是当前处理的键值对数组,其中k
是键(表单元素的name
属性),v
是值(表单元素的值)。
- 回调函数的第一个参数
-
Object.assign({}, p, { [k]: ... })
: 使用Object.assign()
方法将当前的累积对象p
和新键值对合并成一个新对象。新键值对的键为k
,值根据条件判断后生成。 -
p[k] ? (Array.isArray(p[k]) ? p[k] : [p[k]]).concat(v) : v
: 使用三元条件运算符检查累积器p
中是否已存在键k
。如果存在,则检查其值是否为数组(Array.isArray(p[k])
)。如果是数组,则使用concat
方法将当前值v
添加到数组中;否则,将原值和当前值v
创建一个新数组。如果累积器p
中不存在键k
,则将当前值v
作为新值。
使用示例
const formElement = document.querySelector('#myForm');
const serializedData = serialize(formElement);
console.log('Serialized form data:', serializedData);
8、从字符串中移除所有的 HTML 标签
可视版
可复制版
const stripHtml = (html: string): string => new DOMParser().parseFromString(html, 'text/html').body.textContent || '';
代码详解
该函数接受一个 string
类型参数 html
,返回一个 string
类型的结果。这个函数用于从输入的 HTML 字符串中移除所有的 HTML 标签,只保留纯文本内容。
以下是详细解释:
new DOMParser()
: 创建一个DOMParser
实例,用于将 HTML 字符串解析为 DOM 文档。.parseFromString(html, 'text/html')
: 调用parseFromString
方法将输入的 HTML 字符串html
解析为一个text/html
类型的 DOM 文档。.body.textContent
: 获取解析后的 DOM 文档的body
元素的textContent
属性,即该元素及其所有后代元素的纯文本内容。这将自动移除所有 HTML 标签。|| ''
: 使用逻辑或操作符确保结果始终为字符串。如果textContent
为null
(例如,输入的 HTML 字符串为空),则返回空字符串''
。
使用示例
const htmlString = '<h1>Title</h1><p>Paragraph with <b>bold</b> and <i>italic</i> text.</p>';
const plainText = stripHtml(htmlString);
console.log('Plain text content:', plainText);
结语
这些代码片段加上详细的讲解以及使用示例,是不是瞬间就变得通俗易懂了!
作者:HashTang
本文正在参加「金石计划」
原文链接:https://juejin.cn/post/7223043596621267000 作者:HashTang