DOM结构树

174 阅读2分钟

DOM结构树

遍历节点树

节点包含元素->元素节点=DOM 元素

  • parentNode
  • childNodes // 包含 元素节点(类型 1) 属性节点(类型 2) 文本节点(包括换行 类型 3) 注释节点(类型 8) document(类型 9) documentFragment(类型 11)类型
    • firstChild lastChild
    • nextSibling previousSibling 选择下一个 上一个节点
// 封装方法使得childNodes只返回元素节点
// nodeName可以取得节点的名字 不是tagName
// 属性节点没有nodeValue 属性、注释、文本节点有nodeValue属性且可修改
//nodeType 只读

function elementChildren(node) {
  let arr = [],
    children = node.childrenNodes;
  for (let i = 0; i < children.lenth; i++) {
    let tempNode = children[i];
    if (tempNode.nodeType === 1) {
      arr.push(tempNode);
    }
  }
  return arr;
}

遍历元素节点树

这个有兼容性问题

  • parentElement //IE9 及以下不支持
  • children //IE7 及以下不支持
  • childrenElementCount = children.length //IE9 及以下不支持
  • firstElementChild lastElementChild //IE9 及以下不支持
  • nextElementSibling //IE9 及以下不支持 previousElementSibling //IE9 及以下不支持

节点选择的过程

function getElementsByTagNames(ele) {
  // 以选择p元素为例
  // 1.从HTML中把p元素选择出来
  // 2.调用new HTMLParagraphElement()生成Dom元素节点并返回该对象 这样该对象就具有了nodeName nodeType等属性
}
  • getElementById()只在Document上有
  • getElementsByName Element上没有因此
<div>
  <div> </div>
</div>;

const div = document.getElementsByTagName("div")[0];
div.getElementsById(); //会报错的,因为div由HTMLDivElement构造生成
  • getElementByTagName、getElementByClassName、querySelector、querySelectorAll DocumentElement都有
  • HTMLDocument.prototype 上的 body 和 head 属性指向 <head><body>标签
  • Document.prototype 上的 doucmentElement 指向 HTML 标签

练习题原型上添加一个函数获取元素节点的子元素,参数可传可不传,不传的话返回类数组,传的话返回那个 index 的子元素

Element.prototype.eleChildren = function (num = null) {
  let childrenNode = this.childNodes;
  let elementNode = {
    // splice: Array.prototype.splice,
    push: Array.prototype.push,
    length: 0,
  };

  for (let i = 0; i < childrenNode.length; i++) {
    let tempNode = childrenNode[i];
    if (tempNode.nodeType === 1) {
      elementNode.push(tempNode);
    }
  }
  return num ? elementNode[num] : elementNode;
};

const ulDom = document.getElementsByTagName("ul")[0];

节点创建删除

Element 上没有

  • doucument.createElement()
  • document.createTextNode()
  • document.createComment

增加/剪切子节点

appendChild() 在 Node.prototype 上

总是在插入节点的最后,如果插入的节点是本身就是在 dom 上的节点,则会把原节点剪切到指定位置

在指定位置之前插入

c.insertBefore(a,b) 在父级 c 节点下的子节点 b 之前插入 a 节点 该方法是Node.prototype上的方法

删除子节点

父节点.removeChild(子节点) 这个只是把 dom 树上的该节点移除 但是没有释放创建这个节点的内存 而节点自身.remove()则真正销毁并释放内存

innerHTML 和 innerText

这俩方法 HTMLElement.prototype 上都有 Element.prototype 上只有 innerHTML

setAttribute(属性名,属性值)

自定义属性

HTML5 给元素增加了一个 data-*属性 获取时使用元素节点.dataset 可以获取到自定义属性对象 key 为你自己定义的*

创建文档片段

doucment.createDocumentFragment()

fragment 节点 type 是 11 他不是 dom 元素节点所以插入他的话不会在原有 DOM 元素树上插入额外的元素节点,因此 fragment 最适合作为其他要插入的元素节点的外层容器(不会引起页面回流)