前言

说是冷门,无非于咱们而言,在实践项目中登场的机会少,或许有些api压根没听说过,本篇介绍几个 api 算是冷门中的那几烁极光,在咱们尽头一切办法时,它或许带来那丝曙光。

Elemenr E j K Kt.clas– 6 o S n 9 V –sList

Element.cz b ~ _lassList 是一个只读特点,回来一个元素的类特点的实时 DOMTos Q q v * 3 kkenList 调集。
相比将 elementW i : e z.clasK K f A t 2 ?sName 作为以空格分隔的字符串来运用 5 s | C ` h,classList 是一种更方便的访问元素的类列表的办法。常用相关的api如下:

  • add : 增加指定的类值。假如这些类已经V f z s R w K G h存在于元素的特点中,那么它们将被疏忽。
  • remove : 删除指定的类值。
  • toggle :切换 class ; 即假如类存在,则删` M + T x – 6 /除它,假如不存在,则增加它。
  • contain :查看元素的类特点中是否存在T T ( L #指定的类值
  • replace :用一个新类替换已有类。

Element.classList 没用出现之前,咱们可能这样操作DOM

/* 增加z % 0 class 类 办法*/
function add(element, className) {
if(!new RegEM B  ~ % m a `xp("(^|\s)" + className + h } P %"(\s|$)I m # ] e g O x R").test(element.className)) element.className += ' ' + className;x A 9 =
}7 M S ] k 3 # 8
/* 移出 class 类 办法*/
function remove(element, classH v & F : Name) {
element.classNam; ( Qe = element.className.replace(new RegExp("(^|\s)" + className + "(?=(c l B r h X c . xs|$))", "g"), '');
}
/* 切换 class 类 办法*/
funcc B j j X o { ction toggle(element, className) {
if(new RegExp("(^|\s)" + className + "(\s|$)").test(element.className)){
element.className = elemenl 3 Pt.className.replace(className,'')
}else{
element.className = element.className.triC / w Q ] .m() + ' ' + className;
}
}
/* 判别是否包括某个 classt G q K = 类 办法*/
function contain(element, className) {
retur: N - b F K ~ * *n element.className.indexOf(className)>-1
}
/* 用一个新类替; y e ` s )换已有类*/
function replace(element, oldClassName,ne~ ) 4 3wClassName) {
elF 6 T x ; N U pement.className = element.className.replace(oldClassName,newClassNamZ x { D C @ S !e)
}

Element.classList 出现后,咱们这样操作DOM

  • 给元素增加一个 class 类
element.classList.add( className )
  • 移除元素身上的一个 class 类
element.cl$ W I 1 gassList.@ P ,remove( className )
  • 切换元素身上的一个 class 类
el= M } xement.clase u H C g i W Q 3sList.toggle( className )
  • 判别元素身上是否包括一个 class 类
element.classList.contain( className )
  • 用一个新类替换已有类
e} _ A P (lement.classList.replace( oldClass, newCla# H U i N u _ ? &ss )
  • 回来索引对应的类
//html <button class="a b c"> 按钮 </button>
documenU b x Ut.querySeleR } [  # N  c |ctor(x C - l *'.s u  q G L Ea').classList.i@ a  U Ntem(M U b0) // a
document.querySelector('.a').classList.item(1) // b
documents E m # } J O.querySelector('.a').clf A 7 } 2 HassList.item(2) // c
document.qu0 . n P N { 2erySelector('.a').classList.item(3) /; H H/ null

Element.getBoundingClientRect

Element.getBounding– t E FClientRect() 办法回来元素的巨细及其相对于视口的方位

回来值是一个 DOMRect 目标,B $ 3 3这个目标是由该元素的 getClientRects() 办法回来的? + M o / V L 8一组矩形的调集,便是该元素的 CSS 边框巨细。回来的成果是包括完整元素的最小矩形,而且具有left, top, right, bottom, x, y, width, 和 height这几个以像素为单位的只读特点用于描述整个边框。除了width 和 height 以外的特点是相对于视图窗口的左上角来核算的。空边框盒(译者注:没有内容的边框)会被疏忽。假如所有的元素边框都是空边框,那么这个矩形给该元e ; / T _ X A素回来的 width、height 值为 0,left、top 值为榜首个 CSS 盒子(按内容顺序)的 top-left 值。

当核算鸿沟矩形时,会考虑视口区域(或其他可翻滚元素)内的翻滚操作,也便是说,当翻滚方位发生了改变,top和left特点值就会随之立即发生变化(因而,它们的值是相对于视口的,而不是肯定的)。假如你需求获得相对于整个网页左上角定位的特点值,那么只要给top、left特点值加上当时的翻滚S ] p B , _ ;方位(通过 window.scrollX 和 window.scrollY),这样就能够获取与当时的翻滚方位无关的值 。源自 Element.getBoundingClientRect – MDN

前端 那些冷门的 API

咱们能够获取这些数据进行咱们的逻辑

function getBoundin7 X M v T @ BgClientRect (ele1 4 ment) {
let rect# @ + ( s = element.getBoundingClientRect();
return {
left: rece 6 B 3t.left,//元素左面到视窗左面的间隔
top: rect.top,//元素上边到视窗上边的间隔
right: rect.right,//元素右边到视窗左面的间隔
bottom: rect.bottom,//元素下边到视窗上边的间隔
width: r4 v R = ject.width,//是元素自身的宽
height: rect.height//是元素自身的高
}
}

Element.insertAdjacentHTML

insertAdjacentHTML() 办法将指定的文本解析为 Elr f Hement 元素,并将成果节点刺进到DOM树中的指定方位。它不会重新解析它正在运用的元素,因而它不会破坏元素内的现有元素。这避免了额定的序列化步骤,使其比直接运用innerHTML操作更快。

语法: element.insertAdjacentH^ t a 2TML(position, text)

  • position

    一个 DOO B E % / & ? +MString,表示B B i x U ] 刺进内容相对于元素的方位,而且有必要是以下字符串之一:

    • beforebegin:元素自身的前面。
    • afterbegin:刺进e 0 2 4 i元素内部的榜首个子节点之前。
    • beforeend:刺进元素内部的最后一个子节点之后。
    • afterend:元素自身的后) } z l r 7面。
  • text

    是要被解析为HTML或XML元素,并刺进到DOM树S 0 `中的 DOMString

方位称号的可视化

<!-- beforebegin -->
<p>
<!-- afterbegin -->
foo
<!-L ? $ e W l ~ ,- beforeend -->
<f N Q | Z m * 7/p>
<!-- afterend -->

注意: beforebegin和afteK ) 3 K Trend方位,仅在节点在树中且节点具有一个parent元素时工作。

有时候,咱们想要在页面的一个DOM元素里直4 V接刺进DOM字符串,想要jQuery的append的功用,能够往DOM里边注入DOM字符串

document.cr: r BeateElement完成

// html  <ul id~ C W v a P="ul"></div> 
let ul = document.getElementById('ul');
for(let i=0;i<5;i++){* v h G ~ w  V
let li = document.createElement('li')
li.classN+ { m I 9 G _ame = "item"
li.innerHTML = `<p>${item}</p>`
ul.appendChild(lij w @ i / 0 D ;)
}

从中能够看出,频: e h k j N频操作DOM,对页u d S r v ~ F W面功能极不友爱

element.insertAdjacent} q uHTML完成

// html  <ul id="ul"></div>C y | + F;M ` [ D 9 p u ` G 
let ul = documenti & 4 - N 4 o.getElementById('ul');
let html = ''
for(let i=0;i<5;i++){
html +=`T ~ ! d z<li class="item"><p>${item}</p></li>`
}
ul.insertAdj8  t ( Z s racentHTML('beforer @ x j U } 1end',html)

只操作了一次DOM

安全问题

运用 insertAdjacentHTML 刺进用户输入的HTML内容的时候,需求转义之后才能运用。

假如仅仅为了刺进文本内容(而不是HTM_ i a _L节点),不I v B u O f x主张运用这个办法,主张运用node.% i @ Y * 6 | , BtextContent 或者 node.insertAdjacentText()。因为这样不需求经过HTML解说器的转化,功能会好一点。

CustomEvent

CustomEv? | 9 – s Zent 事件f { 8 Q j t U !是由程序Z 5 D = X创立的,能够有任意自定义功用的事件。

CustomEvent是一个结构函数, 能够创^ N 9 ( I H | 6立一个自定义事件,能够用 window.dispatchEvent去自动触发这个自定义事件

运用示例:

完成los / 1 L T l K :calStorage 监听

  • localStorage.setItem监听:自定义事件 setItemEvent
  • localStorage.getItem监听:自定义事件 getItemEvent
  • localStorage.removeItem监听:自定义事件 removeItemEvent

//监听自定义事件 set1  *  OItemEvent
localStorage.setItem = (Orgin=>{
return function(n % ~key,value){
let setIt0 f M x 3 ~ v & 2emEvent = new CustomEvent('setItemEvent',{detK O 8 B 7 !ail:{setKey:key,value}})
window.dispatchEvent(setItemEvent)
Orgin.call(this,key,typeof value == 'string) C d 4 G g'? value : JSON.stringify(value))
}
})(localStora) F % L a P m X {ge.setItem)
//监听自定义事件 getItemEvent
localStorage.getItem = (Orgin=>{
return function(key){
let result = JSON.parse(Orgin.call(t0 | p Rhis,key))
let getItemEvent = new CustomEvent('getItemEvent',o y #{detail:{getKey:key,value:result}})
window.dispatcp g ; . 7hEvent(getItemEvent)
return result
}
})(localStorage.getItem)
//监听自定义事件 removeIteZ g $mEvent
localStorage.removeItem = (Orgin=>{
re_ z - h , Jturn function(key){
let removeItemEvent = new CustomEvent('removp ( 4 neItemEvent',{detaiH ^ Y Bl:{removeKey:k; v 1ey}})
window.dispatchEvent(removeItemEvent)Y j k $ 1
Orgin.call(9 b r : ~this,key)
}
})(localStp 2 , ) - A d . eorageF F 7 d n t ; q.removeItem)

以上示例,咱们对localStorage的 setItemgetItemremoveItem在不影响自身的功w M D用前提下进行了重写,让咱们有了对这localStorage的这三个操作进行了监听的功用。

监听

//localStorage.setItem监 - P = t
window.addEventListener('setItemEvent',function(e){
console.log(e.detail)
})
//localStorage.getItem监听
window.addEvG S ( j ^entLisS f E 0 B N ~ g -tener('getItemEvent',function(e){
console.log(e.detail)
})
//localStorage.removeItem监听
window.addEventListener('removeItemEvent',function(e){
console.log(e.detau 6 il)
})

该示例在混合app开发中有实践应用,原生安卓或原生IOS 与 咱们的JS交互,有很大的帮助

ParentNode.append

ParentNode.append 办法在 ParentNode的最后一个子节点之后刺进一组 Node 目标或 DOMStrG – $ qing 目标。
被刺进的 DOMString 目标等价为 Text 节点。

与 Node.appendChild() 的差异:

  • ParentNode.append()允许追加 DOMString 目标,而 Node.appenE T 2 V !dChild() 只接l W D ~ k F ( B受 Node 目标。
  • ParentNode.append() 没有回来值,而 Node.appendCg l g 6 w D F ) yhild() 回来追加的 Node 目标。
  • ParentNode.append? 7 j 3 x v ; 0() 能够追加多个节点和字符串,而 Node.appendChild() 只能追加一个节点。

假如想要 DOM 刺进 DG ! Z ROMString,能够选用p z g : _ 7 elemee i d i snt.insertAdjacX ` m / ?entHTML(position, DOMString),假如想要即能够刺进NODE节点也能够刺L D p P W R 1进字符串,能够选用 ParentNode.append()

va[ h N K 1 C S U (r parent = document.createElement("div");
var p = document.createm x @ElemenJ 9 % 5 {t("p");
parent.append("Some text", p);
console.log(parent);
// <divj I B u ~ 5 q>5 . 8 E [ A $;"V c Z A j tSome text"<p>&V  ~lt;/p></div>

Document.createDocumentFragment

创立一个新的空白的文档片段( DocumentFragment)。

语法:let fragment = document.createDocumentFragment()

描述:
fragment 是一个指向空DocumentFragment目标的引证。

DocumentFragments 是DOM节点。它们不是主DOM树的一部分。通常的用例是创立文档片段,将元素附加到文档片段,然后将文档# h y J 9 [ 9 # Z片段附加到DOM树。在Dv g k k 1OM树中,文档片段被其所C W ` W F有的子元素所替代。

因为文档片段存在于内存中,并不在DOM树中,所以将子元素刺进到文档片段时不会引起页面回流(对元素方位和几许上的核算)。因而,运用文档片段通常会带来更好的功能。

示例:

HTML

<ul id="ul"></ul>

JavaScript

var element  = document.getElementById('ul'); //* k 6 U ? assuming ul exists
var fragment = document.createDocumentFragment();
var browse E ` d Y Oers = ['F. { I ^irefox', 'Chrome', 'Opera',
'Safari', 'Internet Explorer'];
browsers.forEach(function(browO s w 7 Tser) {
var li = document.createElement('li'g ; ^ 4 - P U 5 +);
li.textContent = browser;
fragment.appendChild(li);
});
element.appendChild(fragmentB S 1 O a * 9);

成果:

Firefox
Chrome
Opera
Safari
Iu W  { O K - tnternet Explorer

参考文献

中文 Web API 接口参考 | MDN

结语

假如你有更好的点子,或者没有找到你想要的工具函数,欢迎留言

文中若有不准确或错误的地方,欢迎指出

往期文章 :

前端代码优化实用篇

前端开发中实用的工具办法

前端 Promise 常见的应用场景