JavaScript高级程序设计(4)
第14章 DOM
>文档对象模型(DOM,Document Object Model)是 HTML 和 XML 文档的编程接口。DOM 表示由多层节点构成的文档,通过它开发者可以添加、删除和修改页面的各个部分。 ### 14.1 节点层级 401 ##### 14.1.1 Node类型 1. **nodeName** 与 **nodeValue**:保存着有关节点的信息。这两个属性的值完全取决于节点类型。在使用 这两个属性前,最好先检测节点类型 2. 节点关系 >每个节点都有一个 childNodes 属性,其中包含一个 NodeList 的实例。NodeList 是一个类数组对象,用于存储可以按位置存取的有序节点,有 length 属性。 3. 操纵节点 ```javascript //在 childNodes 列表末尾添加节点 let returnedNode = someNode.appendChild(newNode); // 作为最后一个子节点插入 returnedNode = someNode.insertBefore(newNode, null); // 作为新的第一个子节点插入 returnedNode = someNode.insertBefore(newNode, someNode.firstChild); // 插入最后一个子节点前面 returnedNode = someNode.insertBefore(newNode, someNode.lastChild); // 替换第一个子节点 let returnedNode = someNode.replaceChild(newNode, someNode.firstChild); // 替换最后一个子节点 returnedNode = someNode.replaceChild(newNode, someNode.lastChild); // 删除第一个子节点 let formerFirstChild = someNode.removeChild(someNode.firstChild); // 删除最后一个子节点 let formerLastChild = someNode.removeChild(someNode.lastChild); ``` 4. 其他方法 - **cloneNode():**会返回与调用它的节点一模一样的节点。接收一个布尔值参数,表示是否深复制。在传入 true 参数时,会进行深复制。复制返回的节点属于文档所有,但尚未指定父节点,所以可称为孤儿节点(orphan)。可以通过 appendChild()、insertBefore()或 replaceChild()方法把孤儿节点添加到文档中。 - **normalize():**是处理文档子树中的文本节点。 ##### 14.1.2 Document类型 > Document 类型是 JavaScript 中表示文档节点的类型。在浏览器中,文档对象 document 是HTMLDocument 的实例(HTMLDocument 继承 Document),表示整个 HTML 页面。document 是 window对象的属性,因此是一个全局对象。 1. 文档子节点 ```javascript let html = document.documentElement; // 取得对<html>的引用 alert(html === document.childNodes[0]); // true alert(html === document.firstChild); // true let body = document.body; // 取得对<body>的引用 let doctype = document.doctype; // 取得对<!doctype>的引用 ``` >一般来说,appendChild()、removeChild()和 replaceChild()方法不会用在 document 对象上。这是因为文档类型(如果存在)是只读的,而且只能有一个 Element 类型的子节点(即<html>,已经存在了)。 2. 文档信息 ```javascript // 读取文档标题 let originalTitle = document.title; // 修改文档标题 document.title = "New page title"; // 取得完整的 URL let url = document.URL; // 取得域名 let domain = document.domain; // 取得来源 let referrer = document.referrer; ``` 3. 定位元素 - getElementById(): - getElementsByTagName() - getElementsByName() - namedItem(): - 对于 name 属性的元素,还可以直接使用中括号来获取 ```javascript 4. 特殊集合//通过id let div = document.getElementById("myDiv"); //通过标签 let images = document.getElementsByTagName("img"); //通过name属性 let myImage = images.namedItem("myImage"); let myImage = images["myImage"]; let radios = document.getElementsByName("color"); ``` 4. 特殊集合 - **document.anchors** :包含文档中所有带 name 属性的<a>元素。 - **document.forms** :包含文档中所有<form>元素(与 document.getElementsByTagName("form")返回的结果相同)。 - document.images :包含文档中所有<img>元素(与 document.getElementsByTagName("img")返回的结果相同)。 - **document.links** :包含文档中所有带 href 属性的<a>元素 5. DOM 兼容性检测 6. 文档写入 > write()简单地写入文本,而 writeln()还会在字符串末尾追加一个换行符(\n)。这两个方法可以用来在页面加载期间向页面中动态添加内容。 > open()和 close()方法分别用于打开和关闭网页输出流。在调用 write()和 writeln()时,这两个方法都不是必需的。 ##### 14.1.3 Element关型 - Element 类型的节点具有以下特征: > - nodeType 等于 1; > - nodeName 值为元素的标签名; > - nodeValue 值为 null; > - parentNode 值为 Document 或 Element 对象; > - 子节点可以是 Element、Text、Comment、ProcessingInstruction、CDATASection、EntityReference 类型。 1. HTML 元素 > 所有 HTML 元素都通过 HTMLElement 类型表示,包括其直接实例和间接实例。每个属性都对应下列属性之一: > > - id,元素在文档中的唯一标识符; > - title,包含元素的额外信息,通常以提示条形式展示; > - lang,元素内容的语言代码(很少用); > - dir,语言的书写方向("ltr"表示从左到右,"rtl"表示从右到左,同样很少用); > - className,用于指定元素的 CSS 类 2. 属性操作 > 与属性相关的 DOM 方法主要有 3 个:getAttribute()、setAttribute()和 removeAttribute()。 > > ```javascript > let div = document.getElementById("myDiv"); > alert(div.getAttribute("id")); // "myDiv" > alert(div.getAttribute("class")); // "bd" > alert(div.getAttribute("title")); // "Body text" > alert(div.getAttribute("lang")); // "en" > alert(div.getAttribute("dir")); // "ltr" > > div.setAttribute("id", "someOtherId"); > div.setAttribute("class", "ft"); > div.setAttribute("title", "Some other text"); > div.setAttribute("lang","fr"); > div.setAttribute("dir", "rtl"); > > div.removeAttribute("class"); > ``` 3. **attributes** 属性 >attributes 属性包含一个NamedNodeMap 实例,是一个类似 NodeList 的“实时”集合。元素的每个属性都表示为一个 Attr 节点,并保存在这个 NamedNodeMap 对象中。 > >```javascript >let id = element.attributes.getNamedItem("id").nodeValue; >let id = element.attributes["id"].nodeValue; >//设置属性的值 >element.attributes["id"].nodeValue = "someOtherId"; >//删除指定名字的属性 >let oldAttr = element.attributes.removeNamedItem("id"); >//给元素添加一个新属性 >element.attributes.setNamedItem(newAttr); >``` 4. 创建元素 >document.createElement()方法创建新元素 > >```javascript >let div = document.createElement("div"); >div.id = "myNewDiv"; >div.className = "box"; >document.body.appendChild(div); >``` 5. 元素后代 ```javascript for (let i = 0, len = element.childNodes.length; i < len; ++i) { if (element.childNodes[i].nodeType == 1) { // 执行某个操作 } } let ul = document.getElementById("myList"); let items = ul.getElementsByTagName("li"); ``` ##### 14.1.4 Text美型 - Text 类型的节点具有以下特征: > nodeType 等于 3; > > nodeName 值为"#text"; > > nodeValue 值为节点中包含的文本; > > parentNode 值为 Element 对象; > > 不支持子节点。 - 文本节点暴露了以下操作文本的方法: >- appendData(text),向节点末尾添加文本 text; >- deleteData(offset, count),从位置 offset 开始删除 count 个字符; >- insertData(offset, text),在位置 offset 插入 text; >- replaceData(offset, count, text),用 text 替换从位置 offset 到 offset + count 的文本; >- splitText(offset),在位置 offset 将当前文本节点拆分为两个文本节点; >- substringData(offset, count),提取从位置 offset 到 offset + count 的文本。 >- 通过 length 属性获取文本节点中包含的字符数量。这个值等于 nodeValue. length 和 data.length。 - 访问文本节点 ```javascript let textNode = div.firstChild; // 或 div.childNodes[0] //修改 div.firstChild.nodeValue = "Some other message"; div.firstChild.nodeValue = "Some <strong>other</strong> message" ``` - 创建文本节点 ```javascript let element = document.createElement("div"); element.className = "message"; let textNode = document.createTextNode("Hello world!"); element.appendChild(textNode); document.body.appendChild(element); ``` - 规范化文本节点 > normalize() 可以合并相邻的文本节点。在包含两个或多个相邻文本节点的父节点上调用 normalize()时,所有同胞文本节点会被合并为一个文本节点,这个文本节点的 nodeValue 就等于之前所有同胞节点 nodeValue 拼接在一起得到的字符串。 - 拆分文本节点 >与 normalize()相反的方法——splitText()。这个方法可以在指定的偏移位置拆分 nodeValue,将一个文本节点拆分成两个文本节点。拆分之后,原来的文本节点包含开头到偏移位置前的文本,新文本节点包含剩下的文本。这个方法返回新的文本节点,具有与原来的文本节点相同的 parentNode。 ##### 14.1.5 Comment美型 - DOM 中的注释通过 Comment 类型表示。Comment 类型的节点具有以下特征: >- nodeType 等于 8 >- nodeName 值为"#comment"; >- nodeValue 值为注释的内容; >- parentNode 值为 Document 或 Element 对象; >- 不支持子节点。 ##### 14.1.6 CDATASection类型 - CDATASection 类型表示 XML 中特有的 CDATA 区块。CDATASection 类型继承 Text 类型,因此拥有包括 splitText()在内的所有字符串操作方法。 ##### 14.1.7 DocumentType类型 - DocumentType 类型的节点包含文档的文档类型(doctype)信息,具有以下特征: >- nodeType 等于 10; >- nodeName 值为文档类型的名称; >- nodeValue 值为 null; >- parentNode 值为 Document 对象; >- 不支持子节点。 ##### 14.1.8 DocumentFragment类型 > 在所有节点类型中,DocumentFragment 类型是唯一一个在标记中没有对应表示的类型。DOM 将文档片段定义为“轻量级”文档,能够包含和操作节点,却没有完整文档那样额外的消耗。 ##### 14.1.9 Attr类型 >元素数据在 DOM 中通过 Attr 类型表示。Attr 类型构造函数和原型在所有浏览器中都可以直接访问。技术上讲,属性是存在于元素 attributes 属性中的节点。 > >Attr 节点很少直接被引用,通常开发者更喜欢使用 getAttribute()、removeAttribute()和 setAttribute()方法操作属性。 ### 14.2 DOM编程 426 ##### 14.2.1 动态脚本 ```javascript //可以像这样通过 DOM 编程创建节点: let script = document.createElement("script"); script.src = "foo.js"; document.body.appendChild(script); //抽象为一个函数 function loadScript(url) { let script = document.createElement("script"); script.src = url; document.body.appendChild(script); } loadScript("client.js"); // var script = document.createElement("script"); script.text = "function sayHi(){alert('hi');}"; document.body.appendChild(script); ``` ##### 14.2.2 动态样式 ```javascript // let link = document.createElement("link"); link.rel = "stylesheet"; link.type = "text/css"; link.href = "styles.css"; let head = document.getElementsByTagName("head")[0]; head.appendChild(link); // function loadStyles(url){ let link = document.createElement("link"); link.rel = "stylesheet"; link.type = "text/css"; link.href = url; let head = document.getElementsByTagName("head")[0]; head.appendChild(link); } loadStyles("styles.css"); ``` ##### 14.2.3 操作表格 ```javascript // 创建表格 let table = document.createElement("table"); table.border = 1; table.width = "100%"; // 创建表体 let tbody = document.createElement("tbody"); table.appendChild(tbody); // 创建第一行 tbody.insertRow(0); tbody.rows[0].insertCell(0); tbody.rows[0].cells[0].appendChild(document.createTextNode("Cell 1,1")); tbody.rows[0].insertCell(1); tbody.rows[0].cells[1].appendChild(document.createTextNode("Cell 2,1")); // 创建第二行 tbody.insertRow(1); tbody.rows[1].insertCell(0); tbody.rows[1].cells[0].appendChild(document.createTextNode("Cell 1,2")); tbody.rows[1].insertCell(1); tbody.rows[1].cells[1].appendChild(document.createTextNode("Cell 2,2")); // 把表格添加到文档主体 document.body.appendChild(table); ``` ##### 14.2.4 使用 **NodeList** ```javascript let divs = document.getElementsByTagName("div"); for (let i = 0; i < divs.length; ++i){ let div = document.createElement("div"); document.body.appendChild(div); } ``` ### 14.3 MutationObserver接口 432 > MutationObserver 接口,可以在 DOM 被修改时异步执行回调。使用 MutationObserver 可以观察整个文档、DOM 树的一部分,或某个元素。此外还可以观察元素属性、子节点、文本,或者前三者任意组合的变化。 ##### 14.3.1 基本用法 ##### 14.3.2 **MutationObserverInit** 与观察范围 ##### 14.3.3 异步回调与记录队列 ##### 14.3.4 性能、内存与垃圾回收
顶部
收展
底部
[TOC]
目录
第1章 JavaScript简介
第2章 在 HTML中使用JavaScript
第3章 语言基础(1)语法变量
第3章 语言基础(2)数据类型
第3章 语言基础(3)操作符
第3章 语言基础(4)语句
第4章 变量、作用域与内存
第5章 基本引用类型
第6章 集合引用类型
第7章 迭代器与生成器
第8 章对象、类与面向对象编程
第9章 代理与反射
第10章 函数
第11章 期约与异步函数
第12章 BOM
第13章 客户端检测
第14章 DOM
第15章 DOM 扩展
第16章 DOM2 和 DOM3
第17章 事件
第18章 动画与 Canvas 图形
第19章 表单脚本
第20章 JavaScript API
第21章 错误处理与调试
第22章 处理 XML
第23章 JSON
第24章 网络请求与远程资源
第25章 客户端存储
第26章 模块
第27章 工作者线程
第28章 最佳实践
相关推荐
WebSocket