JS Web API DOM(1)

从JS基础到JS Web API

  • JS基础知识用于规定语法(ECMA 262标准)
    • JS基础包括:变量的类型和计算、原型和原型链、作用域和闭包
  • JS Web API网页操作的API(W3C标准)
    • JS Web API包括:DOM、BOM、事件绑定、AJAX、存储
  • JS基础知识 是 JS Web API 的基础,两者结合才能应用于实际

DOM

  • DOM操作,即Document Object Model(文件对象模型)
  • 注意: vue和React框架都封装了DOM操作(也就是你不会直接操作DOM)。但DOM操作一直都会是前端工程师的基础、必备知识。

相关问题:
DOM是哪种数据结构
DOM操作的常用API
attribute和property的区别
一次性插入多个DOM节点,考虑性能

DOM的本质

  • 区分HTML文档和DOM:浏览器解析HTML文件构建DOM树(可参考网页的渲染过程
    • HTML文档HTML文档
    • DOM树:DOM是由HTML文档解析出来的一棵“树”【基本的数据结构要有所了解】
  • 总结,DOM的本质就是一颗树,他是有结构的,而HTML文档是没有结构的

DOM节点类型

  • DOM规定,HTML文档中的每个成分都是一个节点
  • 整个文档是一个文档节点
  • 每个HTML标签是一个元素节点
  • 包含在HTML元素中的文本是文本节点
    • 注意: 空格也被看作是文本,文本是文本节点。
  • 每一个HTML属性是一个属性节点(属性节点是另一个层面的理解,在浏览器后台打印childNodes列表的时候,不存在属性节点
    • 在旧 DOM 规范中,属性继承自 Node,是一种特殊的节点。但是DOM4 中已废弃这一条,属性不再是节点。
  • 注释属于注释节点
  • 例子

文本总是存储在文本节点中

  • 在 DOM 处理中一个普遍的错误是,认为元素节点包含文本,其实元素节点包含的是文本节点,文本节点中包含的才是文本!
  • 不过,元素节点的文本是存储在文本节点中的。
  • 在这个例子中:<year>2005</year>,元素节点 <year>,拥有一个值为 “2005” 的文本节点。

“2005” 不是 <year> 元素的值!


DOM节点的属性

  • 每个节点都拥有包含着关于节点某些信息的属性。这些属性是:nodeName(节点名称) 、nodeValue(节点值) 、nodeType(节点类型)

以下面的demo为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
window.onload = function(){
  var element = document.getElementById("span");
  var text = element.firstChild;
  var property=document.getElementById("span").getAttributeNode("id");
}
</script>

<body>
  <div>
    <span id="span">文本节点</span>
  </div>
</body> 

nodeType属性 节点类型

  • nodeType 属性可返回节点的类型。
元素类型 节点类型
普通的DOM元素(ELEMENT_NODE) 1
属性(ATTRIBUTE_NODE) 2
文本元素(TEXT_NODE) 3
注释(COMMENT_NODE) 8
文档(DOCUMENT_NODE) 9
1
2
3
alert("这是元素节点的返回值:"+ element.nodeType);//元素节点返回1
alert("这是文本节点的返回值:"+ text.nodeType);//文本节点返回3
alert("这是属性节点的返回值:"+ property.nodeType);//属性节点返回2

nodeName属性 含有某个节点的名称

  • 元素节点的 nodeName 是标签名称(返回的名称是大写的)
  • 属性节点的 nodeName 是属性名称(返回的名称是大写的)
  • 文本节点的 nodeName 永远是 #text
  • 文档节点的 nodeName 永远是 #document
  • 注释:nodeName 所包含的 XML 元素的标签名称永远是大写的
    1
    2
    3
    alert("这是元素节点的返回值:"+ element.nodeName);//返回的标签名SPAN,注意是大写的
    alert("这是文本节点的返回值:"+ text.nodeName);//返回的#text
    alert("这是属性节点的返回值:"+ property.nodeName);//返回的是属性名,这里是id

nodeValue属性

  • 对于文本节点,nodeValue 属性包含文本
  • 对于属性节点,nodeValue 属性包含属性值
  • nodeValue 属性对于文档节点和元素节点不可用的。
    1
    2
    3
    alert("这是元素节点的返回值:"+ element.nodeValue);//本身就没有意义,这里是试验下的,返回的是null
    alert("这是文本节点的返回值:"+ text.nodeValue);//返回的是文本值 文本节点
    alert("这是属性节点的返回值:"+ property.nodeValue);//返回的是属性值,这里是id的属性值span

DOM节点操作

获取DOM节点

综合案例:
html
js
结果


DOM property 和 HTML attribute

  • property和attribute都是“属性”的意思,但修改property只影响页面效果,并不修改HTML/DOM结构。而修改attribute是同时修改页面效果和HTML/DOM结构的。
  • property是对DOM元素的JS对象的属性进行修改,不会修改HTML结构
  • attribute是直接对DOM元素的属性进行修改,会改变HTML结构
  • 建议使用property,以减少不必要的DOM重新渲染。
  • 可参考这篇博客

DOM property(属性)

  • 浏览器解析完 HTML 后,生成的 DOM 是一个继承自 Object 的常规 JavaScript 对象,因此我们可以像操作任何 JS 对象那样来操作 DOM 对象。
  • 通过获取DOM元素的property(属性)可以获取/修改DOM元素的样式属性
  • property是对DOM元素的JS对象的属性进行修改,不会修改HTML结构
    DOM节点的property
  • nodeName:DOM元素的标签名(比如p、a、div)
  • nodeType:DOM元素的类型一般是1,但文本节点就是3

HTML attribute(特性)

  • 和 DOM property(属性)类似,除了那些规范里定义的标准特性外,也可以通过attribute往HTML上添加非标准的属性。
  • 通过**getAttribute()setAttribute()获取、修改**html的结构。
  • attribute是直接对DOM元素的属性进行修改,会改变HTML结构
    例子
    效果

clonenode()拷贝节点

DOM clonenode()创建指定的节点的精确拷贝


DOM结构操作

DOM是“树”结构的,所以操作也围绕树来看。

appendChild()插入子节点

  • node1.appendChild(node2)可向节点的子节点列表的末尾添加新的子节点
    • node1:父节点
    • node2:新的子节点
  • 如果node2已存在于js文件中,则appendChild()会将node2 移动 到node1之中

例子:
移动节点对象
结果
p1原本存在于div1中,则使用appendChild后,div1中的p1移动到了div2中。

insertBefore()插入子节点

  • insertBefore(newnode,existingnode) 可在已有的子节点前插入一个新的子节点
    • newnode,必须。要插入的节点对象
    • existingnode,必须。要添加新的节点前的子节点

获取父元素parentNode

使用parentNode获取p1元素的父元素:
使用parentNode

获取子节点列表childNodes

  • 注意:childNodes包括 文本节点 !
  • 但是获取子元素列表时不会获取到 元素节点中包含的文本节点,获取到的文本节点实际上是 两个元素节点中的空格 ,空格也是文本节点
    • 比如,p元素中的“一段文字 2”实际上就是 元素节点p 中包含的 文本节点 的内容。但这个文本节点不会显示在div1的childNodes上。
  • 注意:该NodeList对象为LIVE类型的NodeList, 添加或删除子节点都会实时的改变整个NodeList对象,所以我们需要操作它的时候都应该先拷贝出一个对象,然后操作这个对象。

例子:
获取的子节点是3个p节点
使用childNodes
获取到7个节点
可通过`nodeType`或者`nodeName`判断文本节点

过滤出元素节点

  1. 使用call()去调用数组的slice方法将nodeList转为数组
  2. 使用数组的filter()把 文本节点 过滤掉
    • 可以通过nodeType或者nodeName判断
      • 文本节点的nodeType是3,元素节点是1
      • 文本节点的nodeName#text,而元素节点是p之类的

代码
元素节点


获取子元素节点列表children


删除子节点removeChild()

删除子元素