DOM基础

本文主要内容包括DOM概念的介绍、DOM对象的一些常用属性和方法、如何获取DOM节点的父子、相邻元素以及常用的操作DOM节点的方法,也总结了常见方法的浏览器兼容性问题以及使用时需要注意的地方,内容还算全面,可当小手册使用。

1. 什么是DOM

DOM,文档对象模型(Document Object Model)。DOM是 W3C(万维网联盟)的标准,DOM定义了访问HTML和XML文档的标准。在W3C的标准中,DOM是独于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。

按照我的理解,DOM通俗的来说就是一个表示当前页面内容和结构树形Javascript对象,通过”这棵树“,Javascript脚本可以很方便的访问页面上的元素并且动态地对其进行操作,所以DOM其实是JS和页面之间的一个桥梁。

2. 什么是DOM节点

根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:

  • 整个文档是一个文档节点
  • 每个 HTML 元素是元素节点
  • HTML 元素内的文本是文本节点
  • 每个 HTML 属性是属性节点
  • 注释是注释节点

一个DOM节点可以嵌套任意的子节点。

3. DOM节点类型

为了区分不同的DOM节点,W3C制定了一个枚举值来表示不同的节点:

枚举值 类型 描述
1 Element 代表元素
2 Attr 代表属性
3 Text 代表元素或属性中的文本内容
4 CDATASection 代表文档中的 CDATA 部分(不会由解析器解析)
5 EntityReference 代表实体引用
6 Entity 代表实体
7 ProcessingInstruction 代表处理指令
8 Comment 代表注释
9 Document 代表整个文档(DOM 树的根节点)
10 DocumentType 向为文档定义的实体提供接口
11 DocumentFragment 代表轻量级的 Document 对象,能够容纳文档的某个部分
12 Notation 代表 DTD 中声明的符号

可以通过DOM对象的nodeType属性来获取上面的枚举值,例如:

document.nodeType;  // 9
document.body.nodeType; // 1

其中,我们要重点记住的只有两个:

  • 元素节点:nodeType = 1
  • 文本节点:nodeType = 3

经常用来区分一个节点是元素节点还是文本节点,或者过滤出一个节点的子节点中所有的元素节点。

4. DOM属性

  1. innerHTML:代表元素的内容,可以重新赋值,但效率较低

  2. innerText:代表元素内部的文本

  3. nodeName:代表节点的名称

    • nodeName是只读的
    • 元素节点的nodeName与标签名相同
    • 属性节点的nodeName与属性名相同
    • 文本节点的nodeName始终是#text
    • 文档节点的nodeName始终是#document
  4. nodeValue:代表节点的值

    • 元素节点的nodeValueundefinednull
    • 文本节点的nodeValue是文本本身
    • 属性节点的nodeValue是属性值
  5. nodeType: 见上一节

5. DOM元素遍历:获取父子节点和兄弟节点

1. 获取子节点
通过以下属性可以获取元素的子节点,某些属性存在兼容性问题

  • childNodes:获取所有的子节点
  • children: 仅仅获取子元素节点*(1)
  • firstChild: 返回第一个子节点
  • firstElementChild: 返回第一个元素节点*(2)
  • lastChild: 返回第一个子节点
  • lastElementChild: 返回第一个元素节点*(3)

兼容性问题:
(1)children属性IE9以下浏览器依然会包含非元素节点
(2)(3):IE9以下浏览器不支持firstElementChildlastElementChild,即使在受支持的IE版本上,这两个属性也不支持在DocumentDocumentFragment对象上使用

建议:
通常情况下,childNodes结合nodeType属性可以解决绝大多数问题。

2. 获取父节点

  • parentNode:返回父节点
  • parentElement:返回父元素节点*(1)
  • offsetParent:返回一个指向最近的(指包含层级上的最近)包含该元素的定位(position非默认值)元素*(2)

兼容性问题:
(1):IE下parentElement仅仅可以在元素节点上使用
(2):如果没有定位的元素,则offsetParent为最近的 table, table cell或根元素(标准模式下为html;quirks 模式下为body)。当元素的 style.display设置为none时,offsetParent返回null

3. 获取兄弟节点

  • nextSibling:下一个兄弟节点
  • nextElementSibling:下一个兄弟元素节点*(1)
  • previousSibling:前一个兄弟节点
  • previousSiblingElement:前一个兄弟元素节点*(2)

兼容性问题:

(1)(2):IE下nextElementSiblingpreviousSiblingElement仅仅可以在元素节点上使用

6. 元素属性操作

  1. .操作符:document.body.style.backgroundColor = "red";
  2. []操作符:document.body["style"]["backgroundColor"] = "red";document.body["style"]["background-color"] = "red";
  3. setAttribute方法

关于attributeproperty的区别请看:
https://www.cnblogs.com/imwtr/p/4765191.html
https://segmentfault.com/a/1190000003727646

7.元素的查找

  • getElementByXXX系列方法

    • 基于文档

      • document.getElementById(id);:根据id查找
      • document.getElementsByTagName(tagName);:根据标签名查找
      • document.getElementsByTagNameNS(ns, tagName);:在指定的命名空间ns下根据标签名查找, nstagName*时表示匹配所有标签
      • document.getElementsByName(name);:根据name属性查找
      • document.getElementsByClassName(className);:根据class查找*(1)
    • 基于元素

      • element.getElementsByTagName(tagName);:根据标签名查找
      • element.getElementsByTagNameNS(ns, tagName);:在指定的命名空间ns下根据标签名查找, nstagName*时表示匹配所有标签
      • element.getElementsByClassName(className);:根据class查找*(2)
  • querySelector[All]方法
    DocumentElementDocumentFragment实例上均可使用下面的方法:

    • instance.querySelector(selector):查找匹配指定 CSS 选择器的第一个元素*(3)
    • instance.querySelectorAll(selector):查找匹配指定 CSS 选择器的所有元素*(4)

兼容性问题:
(1)(2):IE9以下不支持getElementsByClassName方法
(3)(4):IE8以下不支持querySelectorquerySelectorAll方法
IE9以下不支持DocumentFragment对象

8. DOM节点的操作:创建、插入、删除、修改/替换、移动

  • 创建
    • document.createElement(tagName):创建新的元素节点
    • document.createAttribute(attrName):创建新的属性节点
    • document.createTextNode(text):创建新的文本节点
    • document.createComment(annotation): 创建新的注释节点
    • document.createDocumentFragment():创建文档片段节点

注意:创建后的节点只是存在于内存中,需要通过插入操作才会插入到页面上

  • 插入
    • parent.appendChild(child):向父节点的最后一个子节点后追加新节点
    • parent.insertBefore(newChild, existingChild):向父节点的某个特定子节点之前插入新节点
    • element.setAttributeNode( attributeName ):给元素增加属性节点

注意appendChild方法接受的对象(child)可以是元素/文本/注释/文档碎片节点,但方法调用者(parent)不能是文本/注释节点,insertBefore方法类似。

  • 删除

    • parent.removeChild(child):删除已有的子节点,返回值为被删除的节点
    • element.removeAttribute('attrName'): 删除具有指定属性名称的属性,无返回值
    • element.removeAttributeNode( attrNode ):删除指定属性,返回值为被删除的属性
  • 修改/替换

    • parent.replaceChild(newChild, existingChild):用新节点替换父节点中已有的子节点
    • element.setAttributeNode(attrName):若原元素已有该属性,会更新之,返回被替换掉的属性节点
    • element.setAttribute(attrName, attrValue ):若原元素已有该属性,会更新之,无返回值
  • 移动

    • 若想将一个DOM元素从一个位置移动到另外一个位置,不需要先删除该节点再将该节点新增到新的位置,而只需要查找到该元素,然后直接在目标位置的父元素上直接调用appendChild或者insertBefore方法即可,元素会被自动剪切过去。

参考:
[1] MDN:https://developer.mozilla.org/zh-CN/
[2] CanIUse:https://caniuse.com/
[3] W3C:http://www.w3school.com.cn/htmldom/index.asp
[4] 博客园:https://www.cnblogs.com/yinshuige/p/5812095.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容