——基础不牢,地动山摇。本文来巩固一些原生的dom操作,在此之前先明确一下html的构成。
html 组成
html整个文档是由节点(Node)组成的,那么节点(Node)到底是什么呢,看mdn给出的定义。
Node
Node
是一个接口,各种类型的 DOM API 对象会从这个接口继承。它允许我们使用相似的方式对待这些不同类型的对象;比如,继承同一组方法,或者用同样的方式测试。
大概有这11种类型
常量 | 值 | 描述 |
---|---|---|
Node.ELEMENT_NODE | 1 | 一个 元素 节点,例如 <p> 和 <div> 。 |
Node.ATTRIBUTE_NODE | 2 | 元素 的耦合 属性 。 |
Node.TEXT_NODE | 3 | Element 或者 Attr 中实际的 文字 |
Node.CDATA_SECTION_NODE | 4 | 一个 CDATASection ,例如 <!CDATA[[ … ]]> 。 |
Node.PROCESSING_INSTRUCTION_NODE | 7 | 一个用于 XML 文档的 ProcessingInstruction (en-US) ,例如 <?xml-stylesheet ... ?> 声明。 |
Node.COMMENT_NODE | 8 | 一个 Comment 节点。 |
Node.DOCUMENT_NODE | 9 | 一个 Document 节点。 |
Node.DOCUMENT_TYPE_NODE | 10 | 描述文档类型的 DocumentType 节点。例如 <!DOCTYPE html> 就是用于 HTML5 的。 |
Node.DOCUMENT_FRAGMENT_NODE | 11 | 一个 DocumentFragment 节点 |
<ul class="ul" id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
//对于这样一个html片段来说。如果利用Node.childNodes,获取到的结果如下有五个li,和六个空文本节点组成
所以我们的html 基本都是由这些node节点组成。主要有element元素节点(nodeType为1),文本节点(nodeType为3),注释等等(nodeType为8)。我们详细看一下element元素节点
element元素节点
Element
是一个通用性非常强的基类
*所有属性继承自它的祖先接口 Node
,并且扩展了 Node
的父接口 EventTarget
,
通俗来说就是div
,ul
,li
这些标签就叫元素节点(element),我们通常所说的操作dom,节点大多数就是在此类上,调用对应的方法。根据mdn文档中所述,element继承自node的(element本身是就是node的一种类型)。
那么我们继续追根溯源,Node从其父类型 EventTarget
[1] 继承属性.
EventTarget
接口由可以接收事件、并且可以创建侦听器的对象实现。换句话说,任何事件目标都会实现与该接口有关的这三个方法。
简单来说EventTarget
提供了时间监听器addEventListener等三个方法处理事件,这就解释了所有的element元素都可以调用addEventListener方法。
Node 与 Element 关系
到此我们捋一下他们之间的关系
做完这些铺垫,可以正式进入操作dom了。更多其他的操作可以直接去mdn找Element实例对应的方法。
增加
1.Node.appendChild()
该方法将一个节点附加到指定父节点的子节点列表的末尾处。如果将被插入的节点已经存在于当前文档的文档树中,那么 appendChild()
只会将它从原先的位置移动到新的位置(不需要事先移除要移动的节点)。
2.Element.append()
该方法在 Element的最后一个子节点之后插入一组 Node 对象或 DOMString 对象(就是字符串)。被插入的 DOMString 对象等价为 Text 节点。
与 Node.appendChild() 的差异:
Element.append()
允许追加DOMString
对象,而Node.appendChild()
只接受Node
对象。Element.append()
没有返回值,而Node.appendChild()
返回追加的Node
对象。Element.append()
可以追加多个节点和字符串,而Node.appendChild()
只能追加一个节点。
主要就是插入节点数量的多少,还有就是二者一个定义在node类中,一个定义在element类中。
3.Node.insertBefore()
该方法在参考节点之前插入一个拥有指定父节点的子节点。如果给定的子节点是对文档中现有节点的引用,insertBefore()
会将其从当前位置移动到新位置(在将节点附加到其他节点之前,不需要从其父节点删除该节点)
1.appendChild
<ul class="ul" id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<!-- <li>5</li> -->
</ul>
let li = document.createElement('li');
li.innerHTML = 5
let ul = document.querySelector('ul');
ul.appendChild(li)
2.append
let li1 = document.createElement('li');
let li2 = document.createElement('li')
li1.innerHTML = 5
li2.innerHTML = 6
let ul = document.querySelector('ul');
ul.append(li1,li2)
3.insetBefore
let li = document.createElement('li');
li.innerHTML = 0
let ul = document.querySelector('ul');
let li1 = ul.firstChild;
ul.insertBefore(li,li1)
删除
Element.remove()
该方法,把对象从它所属的 DOM 树中删除。
Node.removeChild()
该方法从 DOM 中删除一个子节点。返回删除的节点。
注意
child
是要移除的那个子节点。node
是child
的父节点。oldChild
保存对删除的子节点的引用。oldChild
===child
. 如果保存了引用js垃圾回收将不会清理内存
用法
//删除第一个li
<ul class="ul" id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<!-- <li>5</li> -->
</ul>
1.remove
let ul = document.querySelector('ul');
let li1 = ul.firstElementChild;
li1.remove()
2.removeChild()
let ul = document.querySelector('ul');
let li1 = ul.firstElementChild;
ul.removeChild(li1)
结果如下
修改
1.Node.replaceChild()
该方法用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点。
2.Element.replaceChildren()
该方法将一个 Node
的后代替换为指定的后代集合。这些新的后代可以为 DOMString
或 Node
对象。
Element.replaceChildren(...nodesOrDOMStrings) // 返回 undefined
parentNode.replaceChild(newChild, oldChild);
查找
如果要找某个具体节点直接利用document.querySelector(),去选择就好。这里只提供寻找父子节点。
父
1.Node.parentNode
该属性返回指定的节点在 DOM 树中的父节点。
parentNode
是指定节点的父节点。一个元素节点的父节点可能是一个元素 (Element
) 节点,也可能是一个文档 (Document
) 节点,或者是个文档碎片 (DocumentFragment
) 节点。
2.Node.parentElement
该属性返回指定的节点在 DOM 树中的父元素节点。
子
1.Element.children
是一个只读属性,返回 一个 Node 的子elements
,是一个动态更新的 HTMLCollection
(一个可迭代的对象)。
2.Node.childNodes
返回包含指定节点的子节点(Node
)的集合,该集合为即时更新的集合(live collection)。