前端必刷系列之红宝书——第 14 章

1,016 阅读5分钟

"红宝书" 通常指的是《JavaScript 高级程序设计》,这是一本由 Nicholas C. Zakas(尼古拉斯·扎卡斯)编写的 JavaScript 书籍,是一本广受欢迎的经典之作。这本书是一部翔实的工具书,满满的都是 JavaScript 知识和实用技术。

不管你有没有刷过红宝书,如果现在还没掌握好,那就一起来刷红宝书吧,go!go!go!

系列文章:

第一部分:基本知识(重点、反复阅读)

  1. 前端必刷系列之红宝书——第 1、2 章
  2. 前端必刷系列之红宝书——第 3 章
  3. 前端必刷系列之红宝书——第 4、5 章
  4. 前端必刷系列之红宝书——第 6 章

第二部分:进阶内容(重点、反复阅读)

  1. 前端必刷系列之红宝书——第 7 章
  2. 前端必刷系列之红宝书——第 8 章
  3. 前端必刷系列之红宝书——第 9 章
  4. 前端必刷系列之红宝书——第 10 章
  5. 前端必刷系列之红宝书——第 11 章

第三部分:BOM 和 DOM (着重学习)

  1. 前端必刷系列之红宝书——第 12、13 章
  2. 前端必刷系列之红宝书——第 14 章

第 14 章 DOM

节点层级

Node 类型

在DOM中,Node 是一个表示文档中的节点的基本接口,它是所有节点类型的基类。Node 接口定义了一些通用的属性和方法,这些属性和方法被所有节点类型所继承。

  1. Node.nodeName 返回节点的名称。

  2. Node.nodeType 返回节点的类型,以数字表示。

    • 1 表示元素节点
    • 2 表示属性节点
    • 3 表示文本节点
    • 8 表示注释节点
    • 等等...
  3. Node.nodeValue 返回或设置节点的值,具体的含义和用法取决于节点的类型。

  4. Node.parentNode 返回节点的父节点。

  5. Node.childNodes 返回一个包含节点所有子节点的 NodeList。

  6. Node.firstChild 返回节点的第一个子节点。

  7. Node.lastChild 返回节点的最后一个子节点。

  8. Node.previousSibling 返回节点的前一个同级节点。

  9. Node.nextSibling 返回节点的后一个同级节点。

// 添加元素节点到父元素
const parentElement = document.getElementById('parentElementId');
parentElement.appendChild(newElement);

// 在父元素的特定位置插入元素节点
const referenceElement = document.getElementById('referenceElementId');
parentElement.insertBefore(newElement, referenceElement);

// 替换节点
const parentElement = document.getElementById('parentElementId');
const oldChild = document.getElementById('oldChildId');
const newChild = document.createElement('div');

parentElement.replaceChild(newChild, oldChild);

// 删除节点
const elementToRemove = document.getElementById('elementToRemove');
elementToRemove.parentNode.removeChild(elementToRemove);

// 复制节点
const originalElement = document.getElementById('originalElementId');
const clonedElement = originalElement.cloneNode(true);

Document 类型

Document 类型是 JS 中表示文档节点的类型

在浏览器中,document 是 HTMLDocument 的实例,表示整个 HTML 页面。

Document 类型的节点有以下特征:

  • nodeType 等于 9
  • nodeName 值为 '#document'
  • nodeValue 值为 null
  • parentNode 值为 null
  • ownerDocument 值为 null
  • 子节点可以是 DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction 或 Comment 类型。

document 对象可用于获取关于页面的信息以及操纵其外观和底层结构

document.documentElement // 取得对<html>的引用
document.childNodes[0] // 取得对<html>的引用
document.firstChild // 取得对<html>的引用

document.body // 取的对<body>的引用
document.doctype // 取的对<!doctype>的引用

所有主流浏览器都支持 document.documentElement、document.body。

文档信息:

document.title // 文档标题,可设置
document.URL // 完整 URL
document.domain // 域名,可设置(限制)
document.referrer // 来源

可以通过设置合法的 document.domain 让两个页面之间通信。

定位元素:

document.getElementById()
document.getElementsByTagName()
document.getElementsByName()

Element 类型

Element 表示 XML 或 HTML 元素,对外暴露出访问元素标签名,子节点和属性的能力。

Element 类型的节点具有以下特征:

  • nodeType 等于 1
  • nodeName 值为元素的标签名
  • nodeValue 值为 null
  • parentNode 值为 Document 或 Element 对象
  • 子节点可以是 Element、Text、Comment、ProcessingInstruction、CDATASection、EntityReference 类型。

操作属性:

// 获取元素属性值
var linkUrl = document.getElementById("myLink")

linkUrl.getAttribute("href");

// 设置元素属性值
linkUrl.setAttribute("href", "https://www.newexample.com");

// 移除元素属性
linkUrl.removeAttribute("attributeName");

attributes:

Element 类型是唯一使用 attributes 属性的 DOM 节点类型。

var element = document.getElementById("myElement");
var allAttributes = element.attributes;

// 遍历所有属性
for (var i = 0; i < allAttributes.length; i++) {
    console.log(allAttributes[i].name + ": " + allAttributes[i].value);
}

Text 类型

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

Text 类型特征:

  • nodeType 等于 3
  • nodeName 值为 '#text'
  • nodeValue 值为节点中包含的文本
  • parentNode 值为 Element 对象
  • 不支持子节点

Comment 类型

DOM 中的注释通过 Comment 类型表示。

Comment 类型的特征:

  • nodeType 等于 8
  • nodeName 值为 '#comment'
  • nodeValue 值为注释的内容
  • parentNode 值为 Document 或 Element 对象
  • 不支持子节点

DocumentType 类型

DocumentType 类型的节点包含文档的文档类型信息。

DocumentType 特征:

  • nodeType 等于 10
  • nodeName 值为 文档类型的名称
  • nodeValue 值为 null
  • parentNode 值为 Document 对象
  • 不支持子节点

DocumentFragment 类型

DocumentFragment 类型是唯一一个在标记中没有对应表示的类型。

DocumentFragment 特征:

  • nodeType 等于 11
  • nodeName 值为 '#document-fragment'
  • nodeValue 值为 null
  • parentNode 值为 null
  • 子节点可以是 Element、Text、Comment、ProcessingInstruction、CDATASection、EntityReference 类型。

DOM 编程

动态脚本

function loadScript(url, callback) {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // 处理脚本加载完成的事件
    script.onload = function () {
        console.log('Script loaded: ' + url);

        // 执行回调函数(可选)
        if (typeof callback === 'function') {
            callback();
        }
    };

    // 将脚本添加到文档头部
    document.head.appendChild(script);
}

// 使用示例
loadScript('path/to/your/script.js', function() {
    // 在脚本加载完成后执行的操作
    console.log('Callback function executed.');
});

MutationObserver 接口

MutationObserver 是 JavaScript 中的一个接口,它提供了一种异步观察DOM(文档对象模型)树变化的能力。使用 MutationObserver 可以监测对DOM的更改,例如元素的添加、删除、属性的修改等。

基本用法

function observeChanges(targetNode, config, callback) {
  var observer = new MutationObserver(callback);
  observer.observe(targetNode, config);
  return observer;
}

function stopObserving(observer) {
  observer.disconnect();
}

// 示例1
var targetNode1 = document.getElementById('element1');
var config1 = { attributes: true, childList: true, subtree: true };
var observer1 = observeChanges(targetNode1, config1, myCallback1);

// 示例2
var targetNode2 = document.getElementById('element2');
var config2 = { attributes: true };
var observer2 = observeChanges(targetNode2, config2, myCallback2);

// 停止观察
stopObserving(observer1);
stopObserving(observer2);
let observer = new MutationObserver(() => console.log('<body> attributes 
changed')); 

observer.observe(document.body, { attributes: true }); 

// 这行代码会触发变化事件
document.body.setAttribute('foo', 'bar'); 

setTimeout(() => { 
 observer.disconnect(); 
 // 这行代码不会触发变化事件
 document.body.setAttribute('bar', 'baz'); 
}, 0); 

setTimeout(() => { 
 // Reattach 
 observer.observe(document.body, { attributes: true }); 
 // 这行代码会触发变化事件
 document.body.setAttribute('baz', 'qux'); 
}, 0); 

// <body> attributes changed 
// <body> attributes changed 

未完待续...

参考资料

《JavaScript 高级程序设计》(第 4 版)