JavaScript DOM 基础
DOM 即文档对象模型,是操作 HTML/XML 文档的一套方法。通过 DOM 操作节点,使页面发生改变,是动态文档技术的核心内容
DOM 的含义
-
DOM 即 document object model,文档对象模型
-
JavaScript 中有三类对象
本地对象 Native Object
Object Function String Number Boolean Error EvalError SyntaxError TypeError RageError ReferenceError URIError Date RegExp
内置对象 Built-in Object
Global: 一类对象的统称,是虚拟的,代表全局 任何方法和属性都在对象之下 如 isNaN()、parseInt、Number()、decodeURL() 等都是 Global 下的方法 如 Math、Infinity、NaN、undefined 等都是 Global 下的属性 本地对象、内置对象是 ECMAScript 的内部对象
宿主对象 Host Object
执行 JS 的环境提供的对象,即浏览器对象 window 对象 -> BOM,不同浏览器间没有固定规范 document 对象 -> DOM,遵从 w3c 规范 document 是 window 下的对象,即 BOM 包含 DOM
-
DOM 是通过浏览器提供的一套方法来操作 HTML 和 XML 文档
元素和节点
-
节点包含元素,元素是节点的一部分,即元素节点
-
节点分类
元素节点、属性节点、文本节点、注释节点、文档节点等
-
元素即元素对象,有 HTMLDivElement、HTMLInputElement、HTMLHtmlElement,继承自构造方法 HTMLElement,HTMLElement 继承自 Node,Node 即节点对象
-
document 继承自构造方法 HTMLDocument 的原型,HTMLDocument 继承自 Document 的原型
document.__proto__ -> HTMLDocument.prototype HTMLDocument.prototype.__proto__ -> Document.prototype
获取元素
-
通过 id 获取元素
document.getElementById(); // 返回对应的 HTMLElement // 对于 getElementById(),IE8 及以下不区分大小写并且可以匹配 name
-
通过类名获取元素集合
兼容 IE9 及以上
document.getElementsByClassName(); // 返回元素集合 HTMLCollection
-
通过标签名获取元素集合
document.getElementsByTagName(); // 返回元素集合 HTMLCollection
-
通过 name 获取元素
document.getElementsByName(); // 返回元素集合 HTMLCollection // 常用于表单元素
-
通过选择器获取对象
兼容 IE8 及以上,是 HTML5 新加入的 web api
document.querySelector(); // 返回选择器选中的第一个节点对象 Node document.querySelectorAll(); // 返回选择器选中的节点列表 NodeList // querySelector、querySelectorAll 比 getElementById 等系列方法性能低
querySelectorAll 方法返回 NodeList,getElements 系列方法返回 HTMLCollection
前者是静态的,获取集合后,增加或删除内容,集合不改变,不具有实时性
而 HTMLCollection 是动态的,随文档操作而改变
遍历节点树
-
parentNode
获取父节点
document.getElementsByTagName("html")[0].parentNode -> document // html 标签元素的 parentNode 是 document // 最高级节点是 document,document 的父节点是 null
-
childNodes
获取子节点集合
document.getElementById("box").childNodes // 包括元素节点、文本节点、注释节点在内
-
firstChild、lastChild
获取第一个或最后一个子节点
document.getElementById("box").firstChild // 第一个子节点 document.getElementById("box").lastChild // 第二个子节点
-
nextSibling、previousSibling
获取上一个或下一个兄弟节点
document.getElementById("box").nextSibling // 上一个兄弟节点 document.getElementById("box").previousSibling // 下一个兄弟节点
-
getAttributeNode()
获取属性节点
document.getElementById("box").getAttributeNode("id") // 获取属性节点 id
遍历元素节点
-
parentElement
获取父元素节点,兼容 IE9 及以上
document.getElementsByTagName("html")[0].parentElement -> null // html 标签元素的 parentElement 是 null
-
children
获取子元素集合,IE6-8 还包含注释节点,IE9 及以上只包含元素节点
document.getElementById("box").children // 只包含元素节点 document.getElementById("box").chilElementCount // children.length
-
firstElementChild、lastElementChild
获取第或最后一个子元素节点,兼容 IE9 及以上
document.getElementById("box").firstElementChild // 第一个子元素节点 document.getElementById("box").lastElementChild // 第二个子元素节点
-
nextElementSibling、previousElementSibling
获取下一个或上一个兄弟元素节点,兼容 IE9 及以上
document.getElementById("box").nextElementSibling // 上一个兄弟元素节点 document.getElementById("box").previousElementSibling // 下一个兄弟元素节点
节点的属性
-
nodeName
返回节点名称、只读
元素节点,元素名称大写document.getElementById("box").nodeName // DIV // 文本节点 -> #text // 注释节点 -> #comment document.nodeName // #document // 文档节点 -> #document
-
nodeValue
返回节点内容,可读写
属性节点、文本节点、注释节点可用document.getElementById("box").getAttributeNode('id').nodeValue // box document.getElementById("box").getAttributeNode('id').value // 效果相同
-
nodeType
返回节点类型对应数字,只读
元素节点 1 属性节点 2 文本节点 3 注释节点 8 document 9 DocumentFragment 11
通过 nodeType 封装 childNodes,筛选出元素节点
function childElementArray(node) { var arr = [], nodes = node.childNodes; for (var i = 0; i < nodes.length; i++) { var item = nodes[i]; if (item.nodeType === 1) { arr.push(item); } } return arr; }
-
attibutes
返回元素节点的属性节点组成的类数组
document.getElementById("box").attributes[0].nodeValue // 获取第一个属性节点的 nodeValue
-
hasChildNodes
返回是否有子节点的布尔值
DOM 结构树
-
DOM 结构树显示了构造方法的继承关系与原型链的走向
-
Document 的原型被 HTMLDocument 继承,同样被 XMLDocument 继承
-
CharacterData 的原型是文本节点和注释节点的祖先
-
HTMLElement 下有与标签对应的多种 HTML...Element,用于构造元素节点
-
需要注意的方法
getElementById、getElementsByName 只在 Document 的原型上,只有 document 可以使用
querySelector、querySelectorAll、getElementsByClassName、getElementsByTagName 在 Document 和 Element 的原型上都有,即 document 和元素节点对象都可以使用
var box = document.getElementById("box"); box.getElementById("list"); // 报错
-
需要注意的属性
document.bady 、document.head、document.title 继承自 HTMLDocoment 的原型
document.documentElement 继承自 Document 的原型
document.bady; // body 标签元素 document.head; // head 标签元素 document.title; // title 元素内文字节点 document.documentElement; // html 标签元素
节点相关操作
-
document.createElement()
创建元素节点
var div = document.createElement("div"); // 传入标签名
-
document.createTextNode()
创建文本节点
-
document.createComment()
创建注释节点
-
document.createDocumentFragment()
创建一个文档碎片,向其中添加节点,再将文档碎片插入文档中,可以提高性能
-
appendChild()
在节点内部的最后添加子节点,并且具有剪切节点功能
var div = document.createElement("div"), text = document.creaetTextNode("文本"); div.appendChild(text); document.body.appendChild(div);
-
insertBefore(a, b)
在节点内部 a 节点之前插入 b 节点
元素节点没有 insertAfter 方法,可以进行封装
Element.prototype.insertAfter = function (target, origin) { var after = origin.nextElementSibling; if (after) { this.insertBefore(target, after); } else this.appendChild(target); } // nextElementSibling 兼容 IE9
-
removeChild()
从文档中删除子节点,但内存中依然保留空间占用
-
remove()
节点调用,删除自身,可以释放内存
-
replaceChild(a, b)
用 a 节点替换子节点 b
-
innerHTML
可以取值,可以赋值,并且赋值可以解析 HTML 代码
-
innerText
可以取值,可以赋值,并且将赋值解析成文本节点,标签符号会被转码成字符实体
firefox 老版本不支持,可使用功能相同的 textContent
-
setAttribute(),getAttribute()
设置、获取属性
var div = document.createElement("div"); div.setAttribute('id', 'box'); div.getAttribute('id'); // 返回 box
-
dataset
HTML5 中以命名
data-
开头的属性,可以通过 dataset 方法访问兼容 IE9 及以上
// document.getElementsByTagName("p")[0].dateset // {name: 'Jett', age: '22'}