跟着MDN学HTML_day_47:(Document接口)

跟着 MDN 学 HTML day_47:深入理解 Document 接口


📑 目录

左列章节 右列章节
[一、访问文档基本信息的属性](#左列章节 右列章节 一、访问文档基本信息的属性 二、快速获取 DOM 元素的便捷属性 三、使用选择器精确查找元素 四、动态创建和修改 DOM 节点 五、操作文档结构和移动节点 六、文档加载状态与可见性 七、全屏操作与指针锁定 八、处理文档中的 Cookie) [二、快速获取 DOM 元素的便捷属性](#左列章节 右列章节 一、访问文档基本信息的属性 二、快速获取 DOM 元素的便捷属性 三、使用选择器精确查找元素 四、动态创建和修改 DOM 节点 五、操作文档结构和移动节点 六、文档加载状态与可见性 七、全屏操作与指针锁定 八、处理文档中的 Cookie)
[三、使用选择器精确查找元素](#左列章节 右列章节 一、访问文档基本信息的属性 二、快速获取 DOM 元素的便捷属性 三、使用选择器精确查找元素 四、动态创建和修改 DOM 节点 五、操作文档结构和移动节点 六、文档加载状态与可见性 七、全屏操作与指针锁定 八、处理文档中的 Cookie) [四、动态创建和修改 DOM 节点](#左列章节 右列章节 一、访问文档基本信息的属性 二、快速获取 DOM 元素的便捷属性 三、使用选择器精确查找元素 四、动态创建和修改 DOM 节点 五、操作文档结构和移动节点 六、文档加载状态与可见性 七、全屏操作与指针锁定 八、处理文档中的 Cookie)
[五、操作文档结构和移动节点](#左列章节 右列章节 一、访问文档基本信息的属性 二、快速获取 DOM 元素的便捷属性 三、使用选择器精确查找元素 四、动态创建和修改 DOM 节点 五、操作文档结构和移动节点 六、文档加载状态与可见性 七、全屏操作与指针锁定 八、处理文档中的 Cookie) [六、文档加载状态与可见性](#左列章节 右列章节 一、访问文档基本信息的属性 二、快速获取 DOM 元素的便捷属性 三、使用选择器精确查找元素 四、动态创建和修改 DOM 节点 五、操作文档结构和移动节点 六、文档加载状态与可见性 七、全屏操作与指针锁定 八、处理文档中的 Cookie)
[七、全屏操作与指针锁定](#左列章节 右列章节 一、访问文档基本信息的属性 二、快速获取 DOM 元素的便捷属性 三、使用选择器精确查找元素 四、动态创建和修改 DOM 节点 五、操作文档结构和移动节点 六、文档加载状态与可见性 七、全屏操作与指针锁定 八、处理文档中的 Cookie) [八、处理文档中的 Cookie](#左列章节 右列章节 一、访问文档基本信息的属性 二、快速获取 DOM 元素的便捷属性 三、使用选择器精确查找元素 四、动态创建和修改 DOM 节点 五、操作文档结构和移动节点 六、文档加载状态与可见性 七、全屏操作与指针锁定 八、处理文档中的 Cookie)

一、访问文档基本信息的属性

在日常开发中,我们经常需要获取当前文档的基本信息,例如文档的标题、URL、字符集等。Document 接口提供了丰富的只读属性来满足这些需求。

代码示例:获取文档基本信息
javascript 复制代码
// 获取文档标题(可读可写)
console.log('文档标题:', document.title);

// 获取文档的完整 URL
console.log('文档 URL:', document.URL);

// 获取文档的字符集
console.log('字符集:', document.characterSet);

// 获取文档的内容类型
console.log('内容类型:', document.contentType);

// 获取文档最后修改时间
console.log('最后修改时间:', document.lastModified);

// 获取引用来源页面
console.log('来源页面:', document.referrer);

核心结论document.title 不仅可以读取,还可以通过赋值动态修改 浏览器标签页上显示的标题。document.URL 返回完整的 URL 字符串,而 document.referrer 则告诉你用户是从哪个页面跳转过来的,这在统计分析中非常有用。document.lastModified 返回页面的最后修改时间字符串。


二、快速获取 DOM 元素的便捷属性

Document 接口提供了一些便捷属性,让我们无需使用选择器就能直接访问文档中的特定元素,这在处理页面结构时极为高效。

代码示例:便捷属性的使用
javascript 复制代码
// 直接获取 <body> 元素
console.log('body 元素:', document.body);

// 直接获取 <head> 元素
console.log('head 元素:', document.head);

// 直接获取 <html> 根元素
console.log('文档根元素:', document.documentElement);

// 直接获取所有链接的集合(HTMLCollection)
const links = document.links;
console.log('链接数量:', links.length);
for (let i = 0; i < links.length; i++) {
  console.log('链接 ' + i + ':', links[i].href);
}

// 直接获取所有表单的集合(HTMLCollection)
console.log('表单数量:', document.forms.length);

// 通过 name 属性直接获取表单
console.log('登录表单:', document.loginForm);

核心结论document.bodydocument.head 是最常用的便捷属性。document.linksdocument.forms 返回的是动态的 HTMLCollection ,当文档中的元素发生增删时,这些集合会自动更新。具有 name 属性的表单和图片元素 会被直接暴露为 document 对象的属性。


⚠️ 【重点 / 面试考点 / 易错点】

便捷属性 返回类型 说明
document.body HTMLBodyElement 页面 body 元素,DOM 就绪前可能为 null
document.head HTMLHeadElement 页面 head 元素
document.documentElement HTMLHtmlElement 根 html 元素
document.forms HTMLCollection 所有 form 元素,即时更新
document.links HTMLCollection 所有带 href 的 a 和 area 元素
document.images HTMLCollection 所有 img 元素
document.scripts HTMLCollection 所有 script 元素
  • document.bodyDOMContentLoaded 之前访问可能为 null
  • document.loginForm 这种通过 name 直接访问的方式是遗留特性,不推荐在新代码中使用

三、使用选择器精确查找元素

当需要根据复杂条件查找元素时,选择器方法 是最强大的工具。Document 接口提供了 querySelectorquerySelectorAll 这两个核心方法。

代码示例:querySelector 与 querySelectorAll
javascript 复制代码
// querySelector 返回匹配的第一个元素
const firstFruit = document.querySelector('.fruit');
console.log('第一个水果:', firstFruit.textContent);

// querySelectorAll 返回所有匹配的元素(静态 NodeList)
const allFruits = document.querySelectorAll('.fruit');
allFruits.forEach(function(fruit, index) {
  console.log(index + ':', fruit.textContent);
});

// 使用复杂的选择器
const highlightFruit = document.querySelector('.fruit.highlight');
console.log('高亮水果:', highlightFruit.textContent);

querySelectorquerySelectorAll 支持完整的 CSS 选择器语法,使得元素查找变得极其灵活。相比之下,getElementByIdgetElementsByClassNamegetElementsByTagName 是更早期的方法。

代码示例:传统查找方法
javascript 复制代码
// 通过 ID 获取元素
const fruitList = document.getElementById('fruitList');
console.log('水果列表元素:', fruitList);

// 通过类名获取元素(HTMLCollection)
const fruitsByClass = document.getElementsByClassName('fruit');
console.log('通过类名获取的水果数量:', fruitsByClass.length);

// 通过标签名获取元素(HTMLCollection)
const allListItems = document.getElementsByTagName('li');
console.log('列表项数量:', allListItems.length);

核心结论querySelectorAll 返回的是静态的 NodeList ,而 getElementsByClassName 返回的 HTMLCollection动态的。在需要频繁操作且 DOM 可能变化时,静态集合更安全。


四、动态创建和修改 DOM 节点

Document 接口提供了丰富的工厂方法用于创建各种类型的节点,这是动态构建页面内容的基础能力。

代码示例:创建各类 DOM 节点
javascript 复制代码
// 创建元素节点
const newDiv = document.createElement('div');
newDiv.className = 'card';
newDiv.style.border = '1px solid #ccc';
newDiv.style.padding = '16px';

// 创建文本节点
const textNode = document.createTextNode('这是动态创建的文本内容');
newDiv.appendChild(textNode);

// 创建注释节点
const commentNode = document.createComment('这是一个注释');
newDiv.appendChild(commentNode);

// 创建文档片段(批量插入优化)
const fragment = document.createDocumentFragment();

const header = document.createElement('h2');
header.textContent = '新闻标题';
fragment.appendChild(header);

const paragraph = document.createElement('p');
paragraph.textContent = '这是一段新闻内容';
fragment.appendChild(paragraph);

// 一次性插入文档片段,只触发一次重排
document.body.appendChild(fragment);
代码示例:使用 append 同时添加多个节点
javascript 复制代码
const span1 = document.createElement('span');
span1.textContent = '标签1 ';
const span2 = document.createElement('span');
span2.textContent = '标签2 ';
const span3 = document.createElement('span');
span3.textContent = '标签3';

// append 可同时添加多个节点和文本
contentDiv.append(span1, span2, span3, ' 这是附加的文本');

核心结论createDocumentFragment 创建轻量级文档片段,批量插入时只触发一次页面重排 ,性能显著优于逐个插入。appendappendChild 的增强版,支持同时添加多个节点和文本。


⚠️ 【重点 / 面试考点】

  • createElement 是最常用的节点创建方法,根据标签名创建新元素
  • createDocumentFragment 用于批量插入优化,只触发一次重排重绘
  • createTextNode 创建文本节点,避免 innerHTML 的 XSS 风险
  • append vs appendChildappend 支持多参数(节点+文本),appendChild 只接受单个节点且返回被添加的节点
  • 文档片段被插入后,其所有子节点会转移到目标容器中,片段本身变为空

五、操作文档结构和移动节点

在实际开发中,经常需要重新组织文档结构。Document 接口提供了多种方法来完成这些操作。

DOM 节点的一个重要特性是它们在文档树中的唯一性 。当你使用 appendChildinsertBefore 操作一个已存在的节点时,浏览器会自动将其从原位置移除并插入到新位置,无需手动删除。

代码示例:移动现有节点
javascript 复制代码
const sourceDiv = document.getElementById('source');
const destDiv = document.getElementById('destination');
const targetParagraph = document.getElementById('moveTarget');

// appendChild 移动已存在节点:自动从原位置移除
destDiv.appendChild(targetParagraph);
console.log('源容器剩余子元素:', sourceDiv.children.length);
console.log('目标容器子元素:', destDiv.children.length);
代码示例:在指定位置插入节点
javascript 复制代码
// 使用 insertBefore 在指定位置插入
const newElement = document.createElement('div');
newElement.textContent = '新插入的元素';
destDiv.insertBefore(newElement, destDiv.firstChild);

// 使用 prepend 在容器开头插入
const prependText = document.createElement('span');
prependText.textContent = '[前置内容] ';
destDiv.prepend(prependText);
代码示例:替换所有子节点
javascript 复制代码
// 使用 replaceChildren 替换所有子元素
const freshContent = document.createElement('p');
freshContent.textContent = '全新的替换内容';
destDiv.replaceChildren(freshContent);

六、文档加载状态与可见性

页面从开始加载到完全可交互,会经历不同的状态。了解这些状态对于优化用户体验和实现加载指示器非常重要。

代码示例:监听 readyState 变化
javascript 复制代码
// readyState 有三个值:
// "loading" - 文档正在加载
// "interactive" - DOM 已解析完毕
// "complete" - 页面及所有资源加载完成

document.addEventListener('readystatechange', function() {
  console.log('readyState 变化为:', document.readyState);

  if (document.readyState === 'interactive') {
    console.log('DOM 已解析完毕,正在加载资源...');
  } else if (document.readyState === 'complete') {
    console.log('页面完全加载完成!');
  }
});
代码示例:DOMContentLoaded 事件
javascript 复制代码
// DOMContentLoaded 在 DOM 解析完成后触发,无需等待图片等资源
document.addEventListener('DOMContentLoaded', function() {
  console.log('DOMContentLoaded 事件触发');
  console.log('此时可以安全地操作 DOM 元素');
});
代码示例:监听页面可见性变化
javascript 复制代码
// visibilitychange 在用户切换标签页或最小化窗口时触发
document.addEventListener('visibilitychange', function() {
  if (document.hidden) {
    console.log('页面被隐藏');
    document.title = '页面已隐藏';
    // 可以在此处暂停动画、视频播放
  } else {
    console.log('页面可见');
    document.title = 'Document 接口示例页面';
    // 恢复动画、视频播放
  }
});

核心结论document.hiddentrue 时表示页面不可见(用户切换了标签页或最小化了窗口)。visibilitychange 事件可以用来暂停或恢复页面中的动画和视频播放,节省系统资源。


七、全屏操作与指针锁定

现代浏览器支持丰富的交互模式,包括全屏显示指针锁定功能,这些能力在游戏和多媒体应用中尤为重要。

代码示例:全屏 API 的使用
javascript 复制代码
const element = document.getElementById('fullscreenTarget');

// 进入全屏
element.requestFullscreen();

// 退出全屏
document.exitFullscreen();

// 监听全屏变化
document.addEventListener('fullscreenchange', function() {
  if (document.fullscreenElement) {
    console.log('进入全屏,当前元素:', document.fullscreenElement);
  } else {
    console.log('退出全屏');
  }
});

// 检查全屏功能是否可用
console.log('全屏支持:', document.fullscreenEnabled);
代码示例:指针锁定 API
javascript 复制代码
const gameArea = document.getElementById('gameArea');

// 请求指针锁定
gameArea.requestPointerLock();

// 监听锁定状态变化
document.addEventListener('pointerlockchange', function() {
  if (document.pointerLockElement === gameArea) {
    console.log('指针已锁定,可以获取原始鼠标移动数据');
  } else {
    console.log('指针已解锁');
  }
});

// 监听锁定失败
document.addEventListener('pointerlockerror', function() {
  console.error('指针锁定失败');
});

核心结论 :全屏 API 和指针锁定 API 都需要用户主动触发 才能启用(如点击按钮),这是浏览器的安全策略。document.fullscreenElement 返回当前全屏元素,null 表示没有元素处于全屏。指针锁定隐藏鼠标并获取原始移动数据,常用于第一人称游戏场景。


⚠️ 【重点 / 面试考点】

API 进入方法 退出方法 查询当前状态 事件
全屏 element.requestFullscreen() document.exitFullscreen() document.fullscreenElement fullscreenchange
指针锁定 element.requestPointerLock() document.exitPointerLock() document.pointerLockElement pointerlockchange
  • 两者都必须由用户手势触发(点击、按键等),不能自动调用
  • fullscreenchangepointerlockchange 事件都绑定在 document
  • Esc 键 可以退出全屏和指针锁定状态
  • document.fullscreenEnabled 可检测浏览器是否支持全屏

Cookie 是 Web 开发中用于客户端存储少量数据的重要机制,Document 接口提供了对 Cookie 的直接读写能力。

document.cookie 的工作方式比较特殊。读取时返回当前页面可访问的所有 Cookie(分号分隔的键值对字符串)。设置时,赋值不会覆盖现有 Cookie,而是追加或更新指定的 Cookie。

代码示例:Cookie 的读写与删除
javascript 复制代码
// 设置 Cookie(不会覆盖已有 Cookie)
function setCookie(name, value, days) {
  let expires = '';
  if (days) {
    const date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    expires = '; expires=' + date.toUTCString();
  }
  document.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/';
}

// 读取所有 Cookie 并解析为对象
function getAllCookies() {
  const cookies = document.cookie.split('; ');
  const cookieObj = {};
  cookies.forEach(function(cookie) {
    if (cookie) {
      const parts = cookie.split('=');
      cookieObj[parts[0]] = decodeURIComponent(parts[1]);
    }
  });
  return cookieObj;
}

// 删除 Cookie(将过期时间设为过去)
function deleteCookie(name) {
  document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/';
}
代码示例:Cookie 操作的实际使用
javascript 复制代码
// 设置 Cookie
setCookie('username', '张三', 7);
setCookie('theme', 'dark', 7);

// 读取 Cookie
const cookies = getAllCookies();
console.log('用户名:', cookies.username);
console.log('主题:', cookies.theme);

// 删除 Cookie
deleteCookie('theme');

核心结论 :删除 Cookie 的本质是将其过期时间设置为过去的时间 ,让浏览器自动清除。设置 Cookie 时必须包含 path=/ 才能确保在整个站点可访问。


九、Document 接口核心方法速查

方法 功能 返回值
document.getElementById(id) 根据 ID 获取元素 Element / null
document.querySelector(selector) 获取首个匹配元素 Element / null
document.querySelectorAll(selector) 获取所有匹配元素 静态 NodeList
document.getElementsByTagName(tag) 根据标签名获取 动态 HTMLCollection
document.getElementsByClassName(cls) 根据类名获取 动态 HTMLCollection
document.createElement(tagName) 创建元素节点 Element
document.createTextNode(text) 创建文本节点 Text
document.createComment(data) 创建注释节点 Comment
document.createDocumentFragment() 创建文档片段 DocumentFragment
Document 接口继承关系

EventTarget
Node
Document
HTMLDocument
document 实例
XMLDocument


✅ 文档总结

  • Document 是 DOM 树的入口节点,代表浏览器中加载的整个 Web 页面
  • 便捷属性如 document.bodydocument.headdocument.formsdocument.links 可直接快速访问常用元素
  • querySelector / querySelectorAll 支持完整 CSS 选择器语法,返回静态 NodeListgetElementsBy* 返回动态 HTMLCollection
  • 节点创建方法:createElementcreateTextNodecreateCommentcreateDocumentFragment(批量插入优化)
  • appendChild 操作已存在节点时会自动从原位置移动,无需手动删除
  • document.readyState 反映文档加载阶段(loadinginteractivecomplete),DOMContentLoaded 在 DOM 就绪时触发
  • visibilitychange 事件 + document.hidden 用于页面可见性检测,可暂停动画和视频节省资源
  • 全屏 API 和指针锁定 API 都必须由用户手势触发,按 Esc 键可退出
  • document.cookie 的特殊机制:读取返回全部 Cookie,设置只更新单个,删除需将过期时间设为过

完整实践示例
javascript 复制代码
// 综合应用:页面加载完成后动态构建内容并管理状态

document.addEventListener('DOMContentLoaded', function() {
  // 1. 获取容器
  const container = document.getElementById('app');

  // 2. 使用文档片段批量创建内容(性能优化)
  const fragment = document.createDocumentFragment();

  const header = document.createElement('header');
  header.innerHTML = '<h1>Document API 演示</h1>';
  fragment.appendChild(header);

  const main = document.createElement('main');

  // 3. 动态创建多个卡片元素
  const items = ['基本信息', '元素查找', '节点操作', '事件处理'];
  items.forEach(function(text, index) {
    const card = document.createElement('div');
    card.className = 'card';
    card.dataset.index = index;
    card.textContent = text;
    main.appendChild(card);
  });

  fragment.appendChild(main);

  // 一次性插入,只触发一次重排
  container.appendChild(fragment);

  // 4. 使用 querySelectorAll 获取静态快照并绑定事件
  const cards = document.querySelectorAll('.card');
  cards.forEach(function(card) {
    card.addEventListener('click', function() {
      console.log('点击了:', this.textContent);
      document.title = '当前选中: ' + this.textContent;
    });
  });

  // 5. 页面可见性检测
  document.addEventListener('visibilitychange', function() {
    if (document.hidden) {
      console.log('页面不可见,暂停定时器');
    } else {
      console.log('页面可见,恢复定时器');
    }
  });

  // 6. 输出文档基本信息
  console.log('文档标题:', document.title);
  console.log('字符集:', document.characterSet);
  console.log('内容类型:', document.contentType);
});

通过动手实践,可以更直观地体会到 Document 接口作为 DOM 入口节点的核心地位,熟练掌握这些 API 能够显著提升前端开发效率和代码质量。


想要解锁更多HTML 核心标签实战、前端零基础入门干货、开发避坑全指南吗?
持续关注,后续将更新CSS 布局实战、JavaScript 交互基础、全站导航开发等硬核内容,带你从新手快速进阶,轻松搞定前端开发!

相关推荐
sheeta19981 小时前
vue_vuex笔记
javascript·vue.js·笔记
学习论之费曼学习法1 小时前
ReAct框架深度解析:让Agent会思考再行动
前端·react.js·前端框架
前端 贾公子1 小时前
从零开始:使用Node.js和Cheerio进行轻量级网页数据提取
前端·vue.js
阿星做前端1 小时前
不想再给ai回复下一步了,于是我给agent装上了一个自动挡
前端·后端·程序员
YuxuanSys-Regen1 小时前
WMMAV&YUXUANSYS/育轩:Dante主机接入手持发射器:让会议音频进入“无线高保真”时代
音视频·腾讯会议·teams·dante·无线手持·音频设备
kcuwu.1 小时前
博客转抖音视频(文件上传版)Coze工作流实现文档(第一版)
人工智能·音视频·coze
毛骗导演1 小时前
Skill 还是 Tool?——从 OpenClaw 源码看 Agent 能力扩展的两种范式
前端·架构
周杰伦fans1 小时前
禁止edge浏览器更新
前端·edge