DOM 详解

DOM

DOM是JS操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个JS对象,从而可以用脚本进行各种操作(比如增删内容)。

文档

文档表示的就是整个的HTML网页文档

对象

对象表示将网页中的每一个部分都转换为了一个对象。

模型

使用模型来表示对象之间的关系,这样方便我们获取对象

文档对象模型(DOM)是网页的编程接口。它给文档(结构树)提供了一个结构化的表述并且定义了一种方式——程序可以对结构树进行访问,以改变文档的结构,样式和内容。

DOM提供了一种表述形式将文档作为一个结构化的节点组以及包含属性和方法的对象。从本质上说,它将web页面和脚本或编程语言连接起来了。

要改变页面的某个东西,JS就需要获得对网页中所有元素进行访问的入口。这个入口,连同对HTML元素进行添加、移动、改变或移除的方法和属性,都是通过DOM来获得的。

浏览器会根据DOM模型,将结构化文档(比如HTML和XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口。所以,DOM可以理解成网页的编程接口。DOM有自己的国际标准,目前的通用版本是DOM 3,DOM 4。

严格地说,DOM不属于JS,但是操作DOM是JS最常见的任务,而JS也是最常用于DOM操作的语言。DOM是浏览器厂商提供的js操作html的api,不同的浏览器厂商提供的api可能不同,所以dom存在兼容性问题(少部分)

1.节点层级

任何 HTML 或 XML 文档都可以用 DOM 表示为一个由节点构成的层级结构。节点分很多类型,每种类型对应着文档中不同的信息和(或)标记,也都有自己不同的特性、数据和方法,而且与其他类型有某种关系。这些关系构成了层级,让标记可以表示为一个以特定节点为根的树形结构。以下面的 HTML为例:

 
<html>
<head>
  <title>Sample Page</title>
</head>
<body>
  <p>Hello World!</p>
</body>
</html>

 

 

 

其中,document 节点表示每个文档的根节点。在这里,根节点的唯一子节点是<html>元素,我们称之为文档元素(documentElement)。文档元素是文档最外层的元素,所有其他元素都存在于这个元素之内。每个文档只能有一个文档元素。在 HTML 页面中,文档元素始终是<html>元素。在 XML 文档中,则没有这样预定义的元素,任何元素都可能成为文档元素。HTML 中的每段标记都可以表示为这个树形结构中的一个节点。元素节点表示 HTML 元素,属性节点表示属性,文档类型节点表示文档类型,注释节点表示注释。DOM 中总共有 12 种节点类型,这些类型都继承一种基本类型。

1.2.节点

DOM的最小组成单位叫做节点(node)。文档的树形结构(DOM树),就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子。

节点的类型有七种:Document、DocumentType、Element、Text、Comment、DocumentFragment。

  • 常用节点

    文档节点(document)

    整个HTML文档document对象作为window对象的属性存在的,我们不用获取可以直接使用。

    元素节点(Element)

    HTML文档中的HTML标签。

    属性节点(Attribute)

    元素的属性 表示的是标签中的一个一个的属性,这里要注意的是属性节点并非是元素节点的子节点,而是元素节点的一部分。

    文本节点(Text)

    HTML标签中的文本内容。

  • 其他节点

    DocumentType

    doctype标签(比如<!DOCTYPE html>)。

    Comment

    注释

    DocumentFragment

    文档的片段

这七种节点都属于浏览器原生提供的节点对象(下面要讲的Node对象)的派生对象,具有一些共同的属性和方法。

1.3.节点树

一个文档的所有节点,按照所在的层级,可以抽象成一种树状结构。这种树状结构就是DOM。

最顶层的节点就是document节点,它代表了整个文档。文档里面最高的HTML标签,一般是<html>,它构成树结构的根节点(root node),其他HTML标签节点都是它的下级。

除了根节点以外,其他节点对于周围的节点都存在三种关系。

  • 父节点关系(parentNode):直接的那个上级节点。

  • 子节点关系(childNode):直接的下级节点。

  • 同级节点关系(sibling):拥有同一父节点的节点。

DOM提供操作接口,用来获取三种关系的节点。其中,子节点接口包括firstChild(第一个子节点)和lastChild(最后一个子节点)等属性,同级节点接口包括nextSibling(紧邻在后的那个同级节点)和previousSibling(紧邻在前的那个同级节点)属性。

2.Node类型

DOM Level 1 描述了名为 Node 的接口,这个接口是所有 DOM 节点类型都必须实现的。Node 接口在 JavaScript中被实现为 Node 类型,在除 IE之外的所有浏览器中都可以直接访问这个类型。在 JavaScript中,所有节点类型都继承 Node 类型,因此所有类型都共享相同的基本属性和方法。

2.1.属性

2.1.1.nodeType

nodeType属性返回一个整数值,表示节点的类型,常用节点类型如下

节点类型 对应常量
文档节点(document) 9 Node.DOCUMENT_NODE
元素节点(element) 1 Node.ELEMENT_NODE
属性节点(attr) 2 Node.ATTRIBUTE_NODE
文本节点(text) 3 Node.TEXT_NODE
文档类型节点(DocumentType) 10 Node.DOCUMENT_TYPE_NODE
注释节点(Comment) 8 Node.COMMENT_NODE
文档片断节点(DocumentFragment) 11 Node.DOCUMENT_FRAGMENT_NODE
<script>
  console.log(document.nodeType); //9
</script>

2.1.2.nodeName

nodeName属性返回节点的名称

<div id="d1">hello world</div>
<script>
  var div = document.getElementById('d1');
  console.log(div.nodeName); //DIV
</script>

2.1.3.nodeValue

nodeValue属性返回一个字符串,表示当前节点本身的文本值,该属性可读写只有文本节点(text)、注释节点(comment)和属性节点(attr)有文本值.

<div id="d1">hello world</div>
<script>
  var div = document.getElementById('d1');
  console.log(div.nodeValue); // null
  // 读
  console.log(div.firstChild.nodeValue); //hello world
  // 写
  div.firstChild.nodeValue = '123';
</script>

2.1.4.textContent

textContent属性返回当前节点和它的所有后代节点的文本内容

<div id="d1">Hello <span>JavaScript</span> DOM</div>
<script>
  var div = document.getElementById('d1');
  console.log(div.textContent); //Hello JavaScript DOM
</script>

2.1.5.nextSibling

nextSibling属性返回紧跟在当前节点后面的第一个同级节点。如果当前节点后面没有同级节点,则返回null

注意:可能会获取到“空格”或“回车”这样的文本节点)

<div id="d1">hello</div><div id="d2">world</div>
<script>
  var div1 = document.getElementById('d1');
  var div2 = document.getElementById('d2');
  console.log(div1.nextSibling); //<div id="d2">world</div>
  console.log(div1.nextSibling === div2); // true
</script>

2.1.6.previousSibling

previousSibling属性返回当前节点前面的、距离最近的一个同级节点。如果当前节点前面没有同级节点,则返回null

<div id="d1">hello</div><div id="d2">world</div>
<script>
  var div1 = document.getElementById('d1');
  var div2 = document.getElementById('d2');
  console.log(div2.previousSibling); //<div id="d1">hello</div>
  console.log(div2.previousSibling === div1); // true
</script>

2.1.7.parentNode

parentNode属性返回当前节点的父节点。对于一个节点来说,它的父节点只可能是三种类型:元素节点(element)、文档节点(document)和文档片段节点(documentfragment)

<div id="d1">hello world</div>
<script>
  var div1 = document.getElementById('d1');
  console.log(div1.parentNode); // body
</script>

2.1.8.parentElement

parentElement属性返回当前节点的父元素节点。如果当前节点没有父节点,或者父节点类型不是元素节点,则返回null

<div id="d1">hello world</div>
<script>
  var div1 = document.getElementById('d1');
  console.log(div1.parentElement); // body
  // 将父元素节点的背景颜色设置为红色
  div1.parentElement.style.backgroundColor = 'red';
</script>

2.1.9.firstChild和lastChild

firstChild属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回null,last则返回最后一个子节点。

<div id="d1">hello world<div>我是子节点</div></div>
<div id="d2"><div>我是子节点</div></div>
<script>
  var div1 = document.getElementById('d1');
  console.log(div1.firstChild); // hello world
  console.log(div1.lastChild); // <div>我是子节点</div>
  var div2 = document.getElementById('d2');
  console.log(div2.firstChild); // <div>我是子节点</div>
</script>

2.1.10.childNodes

childNodes属性返回一个类似数组的对象(NodeList集合),成员包括当前节点的所有子节点

<div id="d1">hello world<div>我是子节点</div></div>
<script>
  var div1 = document.getElementById('d1');
  console.log(div1.childNodes); //NodeList[text, div]
</script>

我们还可以使用for循环来遍历某个节点的所有子节点

var div = document.getElementById('div1');
var children = div.childNodes;
for (var i = 0; i < children.length; i++) {
  // ...
}

2.2.方法

以下方法为常用操作节点的方法,其中最常用的方法是appendChild(),用于在 childNodes 列表末尾添加节点。

注意:以下四个方法都需要父节点对象进行调用!

2.2.1.appendChild(***!)

appendChild方法接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点。该方法的返回值就是插入文档的子节点。

<script>
  // 创建元素节点p
  var p = document.createElement('p');
  // 向p标签插入内容
  p.innerHTML = '我是一个p标签';
  // 将节点插入到body中
  document.body.appendChild(p);
</script>

2.2.2.insertBefore()

insertBefore方法用于将某个节点插入父节点内部的指定位置。

var insertedNode = parentNode.insertBefore(newNode, referenceNode);

insertBefore方法接受两个参数,第一个参数是所要插入的节点newNode,第二个参数是父节点parentNode内部的一个子节点referenceNode。newNode将插在referenceNode这个子节点的前面。返回值是插入的新节点newNode

<div id="parentElement">
  <span id="childElement">foo bar</span>
</div>
<script>
  //创建一个新的、普通的<span>元素
  var sp1 = document.createElement("span");
  // 向span标签插入内容
  sp1.innerHTML = '我是span标签'
  //插入节点之前,要获得节点的引用
  var sp2 = document.getElementById("childElement");
  //获得父节点的引用
  var parentDiv = sp2.parentNode;
  //在DOM中在sp2之前插入一个新元素
  parentDiv.insertBefore(sp1, sp2);
</script>

2.2.3.removeChild()

removeChild方法接受一个子节点作为参数,用于从当前节点移除该子节点。返回值是移除的子节点。

 <div id="d1">
  <span id="s1">我是span标签</span>
</div>
<script>
  var span1 = document.getElementById('s1');
  //创建一个新的div标签
  var div1 = document.createElement("div");
  // 向div标签插入内容
  div1.innerHTML = '我是div1标签';
  // 节点替换
  span1.parentNode.replaceChild(div1, span1);
</script>

2.2.4.replaceChild()

replaceChild方法用于将一个新的节点,替换当前节点的某一个子节点。

var replacedNode = parentNode.replaceChild(newChild, oldChild);

replaceChild方法接受两个参数,第一个参数newChild是用来替换的新节点,第二个参数oldChild是将要替换走的子节点。返回值是替换走的那个节点oldChild。

<div id="d1">
  <span id="s1">我是span标签</span>
</div>
<script>
  var span1 = document.getElementById('s1');
  //创建一个新的div标签
  var div1 = document.createElement("div");
  // 向div标签插入内容
  div1.innerHTML = '我是div1标签';
  // 节点替换
  span1.parentNode.replaceChild(div1, span1);
</script>

2.2.5.其他方法

cloneNode()

方法返回调用该方法的节点的一个副本.

var dupNode = node.cloneNode(deep);

node

将要被克隆的节点

dupNode

克隆生成的副本节点

deep 可选

是否采用深度克隆,如果为true,则该节点的所有后代节点也都会被克隆,如果为false,则只克隆该节点本身。

var p = document.getElementById("para1"),
var p_prime = p.cloneNode(true);

3.Document类型

Javascript通过使用Document类型表示文档。在浏览器中,document对象是HTMLDocument的一个实例,表示整个HTML页面。document对象是window对象的一个属性,因此可以直接调用。HTMLDocument继承自Document。

3.1.属性

documentElement

始终指向HTML页面中的<html>元素。

body

直接指向<body>元素

doctype

访问<!DOCTYPE>, 浏览器支持不一致,很少使用

title

获取文档的标题

URL

取得完整的URL

domain

取得域名,并且可以进行设置,在跨域访问中经常会用到。

referrer

取得链接到当前页面的那个页面的URL,即来源页面的URL。

images

获取所有的img对象,返回HTMLCollection类数组对象

forms

获取所有的form对象,返回HTMLCollection类数组对象

links

获取文档中所有带href属性的<a>元素

3.2.DOM编程界面

HTML DOM 能够通过 JavaScript 进行访问(也可以通过其他编程语言)。

在 DOM 中,所有 HTML 元素都被定义为对象

编程界面是每个对象的属性和方法。

属性是您能够获取或设置的值(就比如改变 HTML 元素的内容)。

方法是您能够完成的动作(比如添加或删除 HTML 元素)。

实例

下面的例子改变了 id="demo" 的 <p> 元素的内容:

<html>
<body>
​
<p id="demo"></p>
​
<script>
    document.getElementById("demo").innerHTML = "Hello World!";
</script>
​
</body>
</html>

在上面的例子中,getElementById 是方法,而 innerHTML 是属性。

getElementById 方法

访问 HTML 元素最常用的方法是使用元素的 id。

在上面的例子中,getElementById 方法使用 id="demo" 来查找元素。

innerHTML 属性

获取元素内容最简单的方法是使用 innerHTML 属性。

innerHTML 属性可用于获取或替换 HTML 元素的内容。

innerHTML 属性可用于获取或改变任何 HTML 元素,包括 <html> 和 <body>。

3.3.查找元素

方法 描述
document.getElementById(id) 通过元素 id 来查找元素
document.getElementsByTagName(name) 通过标签名来查找元素
document.getElementsByClassName(name) 通过类名来查找元素
document.querySelector() 返回文档中匹配指定的CSS选择器的第一元素
document.querySelectorAll() document.querySelectorAll() 是 HTML5中引入的新方法,返回文档中匹配的CSS选择器的所有元素节点列表

getElementById()

返回匹配指定 id 的一个元素。

<div id="d1">我是一个div标签</div>
<script>
  // 查找id为d1的标签
  var div = document.getElementById('d1');
  console.log(div);
</script>

getElementsByTagName()

返回一个HTMLCollection(伪数组),包含匹配指定标签名的所有元素。

<p>我是p标签</p>
<p>我是p标签</p>
<p>我是p标签</p>
<script>
  // 查找所有p标签
  var p = document.getElementsByTagName('p');
  console.log(p);
</script>

getElementsByClassName()

返回一个HTML集合HTMLCollection(伪数组),包含匹配指定类名的所有元素。

<div class="div1">我是div标签</div>
<div class="div1">我是div标签</div>
<div class="div1">我是div标签</div>
<script>
  // 查找class为div1的标签
  var div = document.getElementsByClassName('div1');
  console.log(div);
</script>

document.querySelector()

返回文档中匹配指定的CSS选择器的第一元素

<div id="div1">我是一个div</div>
<div id="div1">我是一个div</div>
<script>
  document.querySelector("#div1").innerHTML = "Hello World!";
</script>

document.querySelectorAll()

document.querySelectorAll() 是 HTML5中引入的新方法,返回文档中匹配的CSS选择器的所有元素节点列表

<div class="div1">我是一个div</div>
<div class="div1">我是一个div</div>
<script>
  console.log(document.querySelectorAll(".div1"));
  var x = document.querySelectorAll(".div1");
  x[0].innerHTML = '我是新的div';
</script>

3.4.添加元素

document.createElement(element)

创建一个新的HTML元素,要与appendChild() 或 insertBefore()方法联合使用。其中,appendChild() 方法在节点的子节点列表末添加新的子节点。insertBefore() 方法在节点的子节点列表任意位置插入新的节点。

<script>
  // 创建元素节点p
  var p = document.createElement('p');
  // 向p标签插入内容
  p.innerHTML = '我是一个p标签';
  // 将节点插入到body中
  document.body.appendChild(p);
</script>

3.5.写入

document.write()

向文档写入文本或 HTML 表达式 或 JavaScript 代码。

<script>
  document.write("<p>Hello world!</p>");
  document.write("<span>Hello DOM!</span>");
  document.write("Hello Weekend!");
</script>

4.Element类型

Element 对象对应网页的 HTML 元素。每一个 HTML 元素在 DOM 树上都会转化成一个Element节点对象。

4.1.属性

attributes:返回一个与该元素相关的所有属性的集合。

classList:返回该元素包含的 class 属性的集合。

className:获取或设置指定元素的 class 属性的值。

clientHeight:获取元素内部的高度,包含内边距,但不包括水平滚动条、边框和外边距。

clientTop:返回该元素距离它上边界的高度。

clientLeft:返回该元素距离它左边界的宽度。

clientWidth:返回该元素它内部的宽度,包括内边距,但不包括垂直滚动条、边框和外边距。

innerHTML:设置或获取 HTML 语法表示的元素的后代。

tagName:返回当前元素的标签名。

4.2.常用方法

方法 描述
element.innerHTML = new html content 改变元素的 innerHTML
element.attribute = value 修改属性的值
element.getAttribute() 返回元素节点的指定属性值。
element.setAttribute(attribute, value) 设置或改变 HTML 元素的属性值
element.style.property = new style 改变 HTML 元素的样式

element.innerHTML

属性设置或获取HTML语法表示的元素的后代。

<div id="div1">我是一个div</div>
<script>
  var d1 = document.getElementById('div1');
  // 获取
  console.log(d1.innerHTML);
  // 设置
  d1.innerHTML = '我是新的内容'
</script>

element.attribute = value

修改已经存在的属性的值

<div id="div1">123</div>
<script>
  var d1 = document.getElementById('div1');
  // 直接将已经存在的属性进行修改
  d1.id = 'div2';
</script>

element.getAttribute()

返回元素节点的指定属性值。

<div id="div1">我是一个div</div>
<script>
  var div = document.getElementById('div1');
  console.log(div.getAttribute('id')); // div1
</script>

element.setAttribute(attribute, value)

把指定属性设置或更改为指定值。

<div id="div1">我是一个div</div>
<script>
  var d1 = document.getElementById('div1');
  // 设置div1的class为divCla
  d1.setAttribute('class', 'divCla');
</script>

element.style.property

设置或返回元素的 style 属性。

<div id="div1">我是一个div</div>
<script>
  var d1 = document.getElementById('div1');
  // 获取div1的style样式
  console.log(d1.style);
  // 设置div1的style
  d1.style.backgroundColor = 'red';
</script>

其他详见HTML DOM Element 对象

Element - Web API 接口参考 | MDN

5.Text类型

Text 节点由 Text 类型表示,包含按字面解释的纯文本,也可能包含转义后的 HTML 字符,但不含 HTML 代码。

5.1.属性及方法

length 文本长度

appendData(text)  追加文本

deleteData(beginIndex,count)  删除文本

insertData(beginIndex,text)  插入文本

replaceData(beginIndex,count,text)  替换文本

splitText(beginIndex)  从beginIndex位置将当前文本节点分成两个文本节点

document.createTextNode(text)  创建文本节点,参数为要插入节点中的文本

substringData(beginIndex,count)  从beginIndex开始提取count个子字符串

综合案例

<div id="container"></div>
<script>
  // 创建文本节点
  var textNode = document.createTextNode('Hello World!');
  // 获取container
  var div = document.getElementById('container');
  // 将文本节点插入container
  div.appendChild(textNode);
  // 替换文本
  textNode.replaceData(0,5,'Hi');
  // 插入文本
  textNode.insertData(0, 'Hello')
</script>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340