DOM相关知识点

此文目的


本文主要是整理DOM相关的知识点,方便往后的查看和各位的查缺补漏。因此重在整理,并不会展开。目前还在持续整理中,打算在16日左右完结。css

Node属性和方法


  • nodeTypehtml

    Node.nodeType// 1为元素节点,2为属性节点,3为文本节点
  • nodeName与tagNamenode

    elementName = Element.tagName;//返回为大写标签名,如DIV,IMG。通常用tagName便可。
    * Attr    ------ Attr.name    属性名
    * Element ------ Element.tagName 标签名
    * Text    ------ nodeName为‘#text’,tagName为undefined
  • nodeValuejquery

    * Text    ------ 文本内容
    * Element ------ null
  • attributes面试

//返回的是NamedNodeMap,不是ARRY。NamedNodeMap是字符串形式的名/值对。无序,且可自动更新。
//获取参照mdn
var attr = element.attributes;
```
  • firstChild:表示某一节点的第一个节点
  • lastChild:表示某一节点的最后一个子节点
  • childNodes:表示所在节点的全部子节点
  • parentNode:表示所在节点的父节点
  • nextSibling:紧挨着当前节点的下一个节点
  • previousSibling:紧挨着当前节点的上一个节点

-方法:segmentfault

Node.hasChildNodes() // 若是包含子节点就返回true

DOM 建立


DOM节点(Node)一般对应于一个标签,一个文本,或者一个HTML属性。DOM节点有一个nodeType属性用来表示当前元素的类型,它是一个整数:数组

  • Element,元素
  • Attribute,属性
  • Text,文本

DOM节点建立最经常使用的即是document.createElement和document.createTextNode方法:浏览器

var el1 = document.createElement('div');
var node = document.createTextNode('hello world!');

DOM 查询

getElementsByTagName等返回的实时的元素集合不须要预先得到全部的元素信息,而.querySelectorAll()会马上收集全部的信息到一个静态的列表里,于是会[下降性能][2]。
能够用instanceof操做符检查节点的原型链:
```
myElement.firstChild.nodeType instanceof Text
```

元素查询的API返回的的结果是DOM节点或者DOM节点的列表。app

//相似于css选择器: 选择classA下的classb元素
document.querySelector(".classA .classB");
// 返回选择的第一个元素.myEl
var el = myEl.querySelector("#foo > div.bar");
// 返回一个文档中a static NodeList,不是即时的
var els = myEl.querySelectorAll(".class");
//元素是否匹配选择器
myElement.matches('div.bar') === true

// 返回的是HTMLCollection,即时更新的。
var el = document.getElementById('ID');
var els = document.getElementsByClassName('CLASS');
var els = document.getElementsByTagName('标签名');
var els = document.getElementsByName('name属性');

Element也提供了不少相对于元素的DOM导航方法:dom

// 获取父元素、父节点
var parent = ele.parentNode;
var parent = ele.parentElement;//非标准

// 获取子节点,子节点能够是任何一种节点,能够经过nodeType来判断
var nodes = ele.children;//元素节点
var nodes = ele.childNodes; //全部节点,包括文本,元素等。可配合nodeType == 1获得元素节点

// 当前元素的第一个/最后一个子元素节点
ele.firstElementChild;//第一个元素节点
ele.firstChild    //第一个节点,通常是文本节点
ele.lastElementChild;//最后一个元素节点
ele.lastChild//最后一个节点

// 下一个/上一个兄弟节点
var el = ele.nextElementSibling;//元素节点
var el = ele.nextSibling;//包括文本节点
var el = ele.previousElementSibling;
var el = ele.previousSibling;

DOM 更改


append,replace,insertBefor的参数el若是已存在DOM中,都会先移除,再插入到新位置。
删除一个元素自身

myElement.parentNode.removeChild(myElement)
// 添加、删除子元素.屡次appendChild到一个父节点会引发浏览器屡次从新渲染,此时能够将节点组合到fragment = document.createDocumentFragment()中。
ele.appendChild(el);//避免链式操做
ele.removeChild(el);//若是有返回值,则存在内存中。

// 替换子元素
//newChild若是存在dom中,则会被移除。replaceNode 为oldChild
replaceNode = parentNode.replaceChild(newChild, oldChild);

// 插入子元素
//newElement若是存在dom中,会先被移除再插入(不想移除可先复制)。
//referenceElement必须有,可为null,为null时,插入到parentElement最后
//return新增长的node(fragment不返回)
newElement = parentElement.insertBefore(newElement, referenceElement);
//没有insertAfter
parentElement.insertBefore(newElement,referenceElement.nextSibling)
//prepend,使用insertBefore代替。
ParentNode.prepend(nodesToPrepend); //IE支持很差
parentElement.insertBefore(newElement, theFirstChild);//jquery中prepend()也是用此方法


//克隆节点
//node须要被克隆的node
//deep为ture,则克隆全部子节点。deep不要省略,由于各版本浏览器默认值不一样。
//深度克隆会克隆全部属性(除addEventListener和后续添加的click事件如:node.onclick = fn,可是会克隆写在dom中的onclick事件),容易致使id重复的问题。
var dupNode = node.cloneNode([deep]);
//document和iframe之间的克隆
var node = document.importNode(externalNode, deep);

修改class,属性和样式


修改属性

.getAttibute(), .setAttribute()和.removeAttribute()这三个方法。这些方法直接修改的是元素的HTML属性(与DOM属性相对),所以会使浏览器从新渲染。浏览器从新渲染不只比只是设置DOM属性代价更高,并且还会产生不指望的后果。做为一个小原则,除非你真的想对HTML“持久化”那些改变,你就只用上面的方法修改与DOM属性不相关的HTML属性(好比colspan)

// 获取一个{name, value}的数组
var attrs = el.attributes;

// 获取、设置属性
var c = el.getAttribute('class');
el.setAttribute('class', 'highlight');

// 判断、移除属性
el.hasAttribute('class');
el.removeAttribute('class');

// 是否有属性设置
el.hasAttributes();  

// Get an attribute value
const value = myElement.value

// Set an attribute as an element property
myElement.value = 'foo'

// Set multiple properties using Object.assign()
Object.assign(myElement, {
  value: 'foo',
  id: 'bar'
})

// Remove an attribute
myElement.value = null

修改class


className和classList

myElement.classList.add('foo')
myElement.classList.remove('bar')
myElement.classList.toggle('baz')

el.className += ' class'

修改样式


在JavaScript里要写成驼峰形式.若是咱们想得到CSS规则的值,咱们能够经过.style属性。然而,经过它只能拿到咱们明确设置过的样式。想拿到计算后的样式值,咱们能够用.window.getComputedStyle()。它能够拿到这个元素并返回一个CSSStyleDeclaration。这个返回值包括了这个元素本身的和继承自父元素的所有样式。

myElement.style.marginLeft = '2em'
window.getComputedStyle(myElement).getPropertyValue('margin-left')
// 动态添加样式规则
var style = document.createElement('style');
style.innerHTML = 'body{color:red} #top:hover{background-color: red;color: white;}';
document.head.appendChild(style);

常见问题

  • innerHTML与outerHTML的区别?

    DOM元素的innerHTML, outerHTML, innerText, outerText属性的区别也常常被面试官问到, 好比对于这样一个HTML元素:

    <div id="main">
        我是测试文本<br/>
    </div>
    let el = document.querySelector("#main");
    console.log("el.innerHTML: ",el.innerHTML); //我是测试文本<br>
    console.log("el.outerHTML: ",el.outerHTML); //<div id="main">我是测试文本<br></div>
    console.log("el.innerText: ",el.innerText); //我是测试文本
    console.log("el.outerText: ",el.outerText); //我是测试文本
    /* el.innerText = "哈哈"; */
    el.outerText = "哈哈";
    • innerHTML:内部HTML;
    • outerHTML:外部HTML;
    • innerText:内部文本;
    • outerText:内部文本;

上述四个属性不只能够读取,还能够赋值。outerText和innerText的区别在于outerText赋值时会把标签一块儿赋值掉,另外xxText赋值时HTML特殊字符会被转义。

clipboard.png

https://jsfiddle.net/langlang...

  • jQuery的html()与innerHTML的区别?

    jQuery的.html()会调用.innerHTML来操做,但同时也会catch异常,而后用.empty(), .append()来从新操做。 这是由于IE8中有些元素的.innerHTML是只读的。见:http://stackoverflow.com/ques...

  • NodeList 和 HTMLCollection区别
    NodeList是节点集合,包括任何节点类型。HTMLCollection是元素集合。NodeList有.forEach(),但IE不支持,因此通常转换成数组再调用

    //[Arry.from()][5]
    Array.from(myElements).forEach(doSth);
    Array.protoType.forEach.call(myElements,doSth);
    [].forEach.call(myElements,doSth)

参考文章:

相关文章
相关标签/搜索