第二十三节:DOM对象

2023-11-01

DOM概述

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

浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口。

DOM 只是一个接口规范,可以用各种语言实现。所以严格地说,DOM 不是 JavaScript 语法的一部分,但是 DOM 操作是 JavaScript 最常见的任务,离开了 DOM,JavaScript 就无法控制网页。另一方面,JavaScript 也是最常用于 DOM 操作的语言。后面介绍的就是 JavaScript 对 DOM 标准的实现和用法。
DOM

提示:Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行访问

节点

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

  • Document:整个文档树的顶层节点
  • DocumentType:doctype标签(比如)
  • Element:网页的各种HTML标签(比如body、a等)
  • Attr:网页元素的属性(比如class=“right”)
  • Text:标签之间或标签包含的文本
  • Comment:注释 DocumentFragment:文档的片段

浏览器提供一个原生的节点对象Node,上面这七种节点都继承了Node,因此具有一些共同的属性和方法。

所有 DOM 节点对象都继承了 Node 接口,拥有一些共同的属性和方法,可通过Node.prototype查看共有属性和方法。

Node常用属性:

Node属性 描述
nodeType 节点的类型
nodeName 返回节点的名称
nodeValue 返回一个字符串,表示当前节点本身的文本值,该属性可读写;只有文本节点(text)、注释节点(comment)和属性节点(attr)有文本值,因此这三类节点的nodeValue可以返回结果,其他类型的节点一律返回null
childNodes 返回一个类似数组的对象(NodeList集合),成员包括当前节点的所有子节点
parentNode 返回当前节点的父节点。对于一个节点来说,它的父节点只可能是三种类型:元素节点(element)、文档节点(document)和文档片段节点(documentfragment)
previousSibling 返回当前节点前面的、距离最近的一个同级节点。如果当前节点前面没有同级节点,则返回null
nextSibling 返回紧跟在当前节点后面的第一个同级节点。如果当前节点后面没有同级节点,则返回null
firstChild 返回当前节点的第一个子节点,如果当前节点没有子节点,则返回null
lastChild 返回当前节点的最后一个子节点,如果当前节点没有子节点,则返回null
textContent 返回当前节点和它的所有后代节点的文本内容

Node常用方法:

Node方法 描述
hasChildNodes() 返回一个布尔值,表示当前节点是否有子节点
appendChild() 接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点。该方法的返回值就是插入文档的子节点。
insertBefore() 接受两个参数,第一个参数是所要插入的节点newNode,第二个参数是父节点parentNode内部的一个子节点referenceNode。newNode将插在referenceNode这个子节点的前面。返回值是插入的新节点newNode
removeChild() 接受一个子节点作为参数,用于从当前节点移除该子节点。返回值是移除的子节点
replaceChild() 用于将一个新的节点,替换当前节点的某一个子节点,接收两个参数 parentNode.replaceChild(newChild, oldChild);
cloneNode() 用于克隆一个节点。它接受一个布尔值作为参数(默认false),表示是否同时克隆子节点。它的返回值是一个克隆出来的新节点。
normalize() 用于清理当前节点内部的所有文本节点(text)。它会去除空的文本节点,并且将毗邻的文本节点合并成一个,也就是说不存在空的文本节点,以及毗邻的文本节点。

具体案例可参考document节点

document.nodeName;//'#document'
document.nodeType;//9
document.nodeValue;//null
document.firstChild;
document.lastChild;
// HTML 代码如下
// <div id="d1">hello world</div>
var div = document.getElementById('d1');
div.nodeName // "DIV"
div.firstChild.nodeValue // "hello world"   div.firstChild属于文本节点

//克隆节点
document.querySelector('ul').cloneNode(true);//包括当前节点下面的子节点
该方法有一些使用注意点。
(1)克隆一个节点,会拷贝该节点的所有属性,但是会丧失addEventListener方法和on-属性(即node.onclick = fn),添加在这个节点上的事件回调函数。

(2)该方法返回的节点不在文档之中,即没有任何父节点,必须使用诸如Node.appendChild这样的方法添加到文档之中。

(3)克隆一个节点之后,DOM 有可能出现两个有相同id属性(即id="xxx")的网页元素,这时应该修改其中一个元素的id属性。如果原节点有name属性,可能也需要修改。

不同的nodeType值对应的节点:

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

1、Document文档节点

Document几个重要的属性:

属性 描述
document.documentElement 返回 html元素
document.body 返回 body 元素
document.title 返回 title 元素
document.domain 返回 返回文档服务器的域名(可获取也可修改,但是只能从高级向低级修改,不能从低级向高级修改)
document.referrer 返回引用的 URI(链接文档)
//获取页面title
document.title;//'JavaScript HTML DOM 文档'
//修改页面title
document.title='JavaScript';
//获取页面域名
document.domain;//'csdn.net'
//修改页面域名跟location.href不同,location.href可以修改为任意域名,但document.domain只能从低级到高级修改,不能从高级向低级修改(二级三级域名改一级域名可以,一级改二级三级不可以)
location.href='http://baidu.com';
document.domain='http://baidu.com';//报错

Document 对象方法
1、获取节点

方法名 描述
getElementById() 返回对拥有指定 id 的第一个对象的引用。
getElementsByName() 返回带有指定名称的对象集合。
getElementsByTagName() 返回带有指定标签名的对象集合。
getElementsByTagName() 返回带有指定标签名的对象的集合
document.querySelector() 接受一个 CSS 选择器作为参数,返回匹配该选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null
document.querySelectorAll() 与querySelector用法类似,区别是返回一个NodeList对象,包含所有匹配给定选择器的节点

注意:后三个的写法elements是带S的;后三个得到都是一个集合,用数组的查找方式获取对应标签,下标从0开始

// HTML 代码如下
// <div id="para1">hello world</div>
document.getElementById('para1');
// 表单为 <form name="x"></form>
var forms = document.getElementsByName('x');
forms[0].tagName // "FORM"
//查找类
document.getElementsByClassName(names);//单个类
document.getElementsByClassName('foo bar');//多个类,空额分割
//查找标签名
document.getElementsByTagName('*'); //查找所有标签
document.getElementsByTagName('p')[0]; //查找第一个p标签
//HTML代码
// <div class="myclass">hello world</div>
// <div class="myclass">第二行</div>
// <div class="myclass">第三行</div>
document.querySelector('.myclass'); //得到第一个类名为myclass的标签
document.querySelectorAll('.myclass'); //得到所有类名为myclass的标签,通过下标获取对应标签,下标从0开始

document.body.querySelector("style[type='text/css'], style:not([type])");
element.querySelector('div, p')

2、创建节点

方法名 描述
createElement() 生成元素节点,并返回该节点
createTextNode() 生成文本节点(Text实例),并返回该节点。它的参数是文本节点的内容
var newDiv = document.createElement('div');
var newContent = document.createTextNode('Hello');
newDiv.appendChild(newContent);

Document对象属性和方法参考

2、Element标签节点(标签节点,如div、body、a、p均属于标签节点)

document.body.nodeName;//'BODY'
document.body.firstChild.nodeName;//'svg'
document.body.lastChild.nodeName;'DIV'

除了Node原生属性 nodeType、nodeName、nodeValue常用到的这三个,还有一些属性经常使用,列举如下。

element属性 描述
Element.id 返回指定元素的id属性,该属性可读写
Element.title 用来读写当前元素的 HTML 属性title。该属性通常用来指定,鼠标悬浮时弹出的文字提示框。
Element.dir 用于读写当前元素的文字方向,可能是从左到右(“ltr”,默认ltr),也可能是从右到左(“rtl”)
Element.className 用来读写当前元素节点的class属性。它的值是一个字符串,每个class之间用空格分割。
Element.innerHTML 返回一个字符串,等同于该元素包含的所有 HTML 代码。该属性可读写,常用来设置某个节点的内容。它能改写所有元素节点的内容,包括HTML和body元素。
Element.outerHTML 返回一个字符串,表示当前元素节点的所有 HTML 代码,包括该元素本身和所有子元素。
Element.clientHeight 元素节点的 CSS 高度,只对块级元素生效,对于行内元素返回0;还包括padding部分,但是不包括border、margin;如果有水平滚动条,还要减去水平滚动条的高度。注意,这个值始终是整数,如果是小数会被四舍五入。
Element.clientWidth 返回元素节点的 CSS 宽度,同样只对块级元素有效,也是只包括元素本身的宽度和padding,如果有垂直滚动条,还要减去垂直滚动条的宽度
Element.id 该属性可读写
Element.id 该属性可读写
// HTML 代码为 <p id="foo">
var p = document.querySelector('p');
p.id // "foo"
// HTML 代码 <div class="one two three" id="myDiv"></div>
var div = document.getElementById('myDiv');
div.className;// "one two three"
//获取document中body的标题
document.body.title;//''
//修改标题
document.body.title='body标题';
//<a class="link" href="http://www.baidu.com">百度</a>
var link=document.querySelector('.link');
link.target='_blank'; //设置链接打开方式
link.title='百度';//设置title
link.href='https://www.taobao.com/'; //修改href链接

元素节点提供六个方法,用来操作属性

  • getAttribute():读取某个属性的值
  • getAttributeNames():返回当前元素的所有属性名
  • setAttribute():写入属性值
  • hasAttribute():某个属性是否存在
  • hasAttributes():当前元素是否有属性
  • removeAttribute():删除属性
// HTML 代码为
//<div id="div1" align="left">div内容</div>
var div = document.getElementById('div1');
//读取属性值
console.log(div.getAttribute('align'));//获取align属性的值 "left"
//读取所有属性名
console.log(div.getAttributeNames());//获取div1标签上的所有属性 ["id", "align"]
//新增属性
div.setAttribute('title','新增标题');
console.log(div.getAttributeNames());//(3) ["id", "align", "title"]
//检查某个属性是否存在
console.log(div.hasAttribute('title'));//true
console.log(div.hasAttribute('align'));//true
console.log(div.hasAttribute('class'));//false
//判断是否有属性
console.log(div.hasAttributes());
//移除指定属性
div.removeAttribute('title');//移除title属性

3、text文本节点

//获取文本内容

// HTML 代码为
//<div id="div1" align="left">div内容</div>
console.log(div.childNodes[0]); //"div内容"
console.log(div.firstChild); //"div内容"
console.log(div.childNodes[0].nodeType); //3 文本节点

编辑Text节点文本内容的方法:

  • appendData():在Text节点尾部追加字符串。
  • deleteData():删除Text节点内部的子字符串,第一个参数为子字符串开始位置,第二个参数为子字符串长度。
  • insertData():在Text节点插入字符串,第一个参数为插入位置,第二个参数为插入的子字符串。
  • replaceData():用于替换文本,第一个参数为替换开始位置,第二个参数为需要被替换掉的长度,第三个参数为新加入的字符串。
  • subStringData():用于获取子字符串,第一个参数为子字符串在Text节点中的开始位置,第二个参数为子字符串长度
  • splitText() :将Text节点一分为二,变成两个毗邻的Text节点。它的参数就是分割位置(从零开始),分割到该位置的字符前结束。如果分割位置不存在,将报错
// HTML 代码为
// <p>Hello World</p>
var pElementText = document.querySelector('p').firstChild;
console.log(pElementText);
pElementText.appendData('!!!');
pElementText.deleteData(0,1);
pElementText.insertData(0, 'Hello ');
pElementText.replaceData(0,5,'替换');//从0开始替换,替换5个字符,替换为文本"替换"
console.log(pElementText.substringData(0,2));//替换
console.log(pElementText.splitText(2));//" ello World!!!"
//插入文本
var newContent = document.createTextNode('创建文本');
document.querySelector('p').appendChild(newContent);

当把节点插入到DOM树中,使用appendChild方法时,会造成浏览器的重绘(插入节点浏览器需要将DOM重新绘制出来,重新绘制的过程被称之为重绘),如果循环语句插入多个节点多次重绘会影响浏览器性能,可以通过打包,一次性插入来解决。

document.createDocumentFragment():document.createDocumentFragment方法生成一个空的文档片段对象

//<ul id="ul"></ul>
var list=['列表一','列表二','列表三','列表四','列表五']
var docfrag = document.createDocumentFragment();
list.forEach(function (e) {
  var li = document.createElement('li');
  li.textContent = e;
  docfrag.appendChild(li);
});
var element  = document.getElementById('ul');
element.appendChild(docfrag);

注意:IE浏览器,使用文档片段DocumentFragment的性能并不会更好,反而变差;chrome和firefox浏览器,使用文档片段DocumentFragment可以提升性能

DOM节点相关学习文章

注意:HTML不区分大小写,JS区分大小写,当HTML的属性需要用JS的方式表示,无论HTML中使用的大写还是小写,在js中均要转变为小写

4、扩展:html5自定义属性

html5中我们可以使用data-前缀设置我们需要的自定义属性,来进行一些数据的存放,例如我们在标签上设置语言

//<a href="javascript:;" data-lang="English">测试</a>
//<div data-lang="English">测试</div>
var alink=document.querySelector('a');
console.log(alink.dataset.lang);//English 获取data-lang的值
alink.setAttribute('data-lang','Chinese'); //溪公安data-lang的值
//删除自定义属性
delete alink.dataset.foo;

如果浏览器支持dataset,则会弹出注释内容;如果浏览器不支持dataset则会报错;目前在Opera 11.1+、Chrome 9+下可以通过javascript使用dataset访问你自定义的data属性。

除了dataset属性,也可以用getAttribute(‘data-lang’)、removeAttribute(‘data-lang’)、setAttribute(‘data-lang’)、hasAttribute(‘data-lang’)等方法操作data-*属性

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第二十三节:DOM对象 的相关文章

随机推荐

  • 【算法】队列——解密QQ号

    新学期开始了 小哈是小哼的新同桌 小哈是个小美女哦 小哼向小哈询问QQ号 小哈当然不会直接告诉小哼啦 原因嘛你懂的 所以小哈给了小哼一串加密过的数字 同时小哈也告诉了小哼解密规则 规则是这样的 首先将第1个数删除 紧接着将第2个数放到这串数
  • CentOS7添加永久路由之一

    一 默认在系统中添加的路由会随着网络重新启动丢失 root vm al bj2 web01 route n Kernel IP routing table Destination Gateway Genmask Flags Metric R
  • Vue 渲染流程详解

    在 Vue 里渲染一块内容 会有以下步骤及流程 第一步 解析语法 生成AST 第二步 根据AST结果 完成data数据初始化 第三步 根据AST结果和DATA数据绑定情况 生成虚拟DOM 第四步 将虚拟DOM 生成真正的DOM插入到页面中
  • python针对Excel文件处理

    一 Excel文件处理介绍 需要用到第三方库 openpyxl 最常用 xlrd xlwt pandas 安装第三方库 pip install openpyxl 二 openpyxl模块 openpyxl模块的三大重要组件 1 工作簿 包含
  • 前置声明(Forward declaration)

    前置声明是指声明一个类或结构体而不定义它 比如 class A struct B 在声明之后 定义之前 该类或结构体被称为不完全类型 incompletion type 意思是 知道类型A和B 但不知道他包含哪些内容 不完全类型的使用有一些
  • pip指定路径安装文件

    pip指定路径安装文件 由于某些原因 我们使用pip命令安装一些模块时 速度慢的离谱 所以我们有时会用其他方式在网上下载资源包 以zh core web lg 2 3 1 tar gz为例 再通过pip安装 格式 pip install t
  • loadrunner+fiddler代理录制

    今天在录制脚本的时候遇到一个问题 因为公司的电脑IE版本为IE9 且不能降低版本 所以设置了个loadrunner代理 代理是设置了应用服务器的IP和端口 但是在录制的时候很多静态文件没有出来 因为loadrunner代理只能代理录制代理I
  • Spark-特征选择(scala)

    spark特征选择 基于scala语言编写 ChiSqSelector 特征选择试图识别用来构建模型的相关特征 它减少了特征空间的大小 既可以提高速度又可以提高统计学习行为的结果 ChiSqSelector实现了卡方特征选择 它能够操作带有
  • s捕捉异常处理是使用js try catch方式

    在JavaScript可以使用try catch来进行异常处理 例如 try foo bar catch e alert e name e message 目前我们可能得到的系统异常
  • Kali使用VMware安装方法。

    Kali使用VMware安装方法以及修改中文界面 一直使用的Centos系统 今天我们换种口味 来玩玩kali 1 什么是kali 手指犹如轻快的舞步在键盘上不断地敲击着 清脆的咔擦声音刺回荡在空荡的房间 黑绿色的屏幕光反射在一张恐怖的面具
  • 微信小程序是怎么做的?

    微信小程序是一种轻量级的应用 它可以在微信内部直接使用 无需下载和安装 那么 微信小程序是怎么做的呢 微信小程序制作的大概步骤 微信小程序制作主要包括以下几个步骤 注册小程序账号 在小程序制作工具创建小程序 设计小程序页面 提交审核 成功发
  • Webpack学习

    webpack是一种打包工具 安装 npm install webpack webpack cli webpack dev server D webpack配置文件 可命名 webpack config js 单个总的配置文件 也可以拆分成
  • node 模块引入与加载机制

    一 说在前面 在Node js中 以模块为单位划分功能 通过一个完整的模块加载机制使得开发人员可以将应用程序划分为多个不同的部分 模块的使用可以提高代码重用率 提高应用程序的开发效率 而且开发人员可以根据具体的需求引入第三方模块或者自定义模
  • Java 8中 Objects 类源码实现与分析

    Objects 类位于 java util 包下 自 JDK 1 7 版本新增的 它是一个 final 类 不能被继承 且构造函数是 private 的 不能被实例化 它提供了一系列操作Object对象的静态方法 通常会被当做工具类去使用
  • org.junit.jupiter.api不存在如何解决

    问题描述 报错信息 解决方案 在pom xml中添加依赖 代码如下
  • SpringCloud简单实战

    我学习时搭建的父子项目 所以文章里依赖没有
  • Windows 系统cmd设置添加静态路由方式

    电脑上添加静态路由 cmd设置路由 方法 步骤 1 首先在 运行 窗口输入cmd 按WIN R打开运行窗口 然后回车进入命令行 输入 route add 10 253 251 0 mask 255 255 255 0 p 192 254 1
  • 前端实际开发中的命名规范(个人建议)

    如果说计算机科学只存在两个难题 缓存失效和命名 那我觉得前端的命名占有一席之地 让人难以理解的命名方式 单词拼写错误 中英文混用 以数字1 9或者以a z命名 中文拼音命名 强制缩写 命名方法 每个单词之间用 或者 连接 小驼峰 除第一个单
  • JavaScript做简单的购物车效果(增、删、改、查、克隆)

    比如有时候遇到下面这种情况 点击加入购物车 然后在上方的购物车中动态的添加商品以及商品的信息 我们就可以通过JavaScript实现简单的这些操作 首先我们需要在html文档中 通过css对页面的布局做一些简单的设置 并创建两个模板 其di
  • 第二十三节:DOM对象

    DOM概述 DOM 是 JavaScript 操作网页的接口 全称为 文档对象模型 Document Object Model 它的作用是将网页转为一个 JavaScript 对象 从而可以用脚本进行各种操作 比如增删内容 浏览器会根据 D