miller
发布于

什么是 DOM

文本主要介绍文档对象模型 (DOM), 了解什么是 DOM 操作,以及如何使用砶 DOM API 与 JS 中的 Web 页面进行交互。

什么是 DOM ?

DOM(文档对象模型) 是针对于 xml 但是扩展用于 HTML 的应用程序编程接口,定义了访问和操作 HTML 的文档的标准。

W3C 文档对象模型是中立于平台和语言之间的接口,它允许程序和脚本动态的访问和更新文档的内容、结构、样式。总之 HTML 是关于如何获取、修改、添加和删除 HTML 元素的标准。

DOM 分层节点

DOM 的分层节点一般被称作是 DOM 树,树中的所有节点都可以通过脚本语言例如 JS 进行访问,所有 HTMlL 元素节点都可以被创建、添加或者删除。

在 DOM 分层节点中,页面就是用分层节点图表示的。

  • 整个文档是一个文档节点,就想是树的根一样。
  • 每个 HTML 元素都是元素节点。
  • HTML 元素内的文本就是文本节点。
  • 每个 HTML 属性时属性节点。

当咱们访问一个 web 页面时,浏览器会解析每个 HTML 元素,创建了 HTML 文档的虚拟结构,并将其保存在内存中。接着,HTML 页面被转换成树状结构,每个 HTML 元素成为一个叶子节点,连接到父分支。
考虑以下 Html 结构:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>A super simple title!</title>
</head>
<body>
<h1>A super simple web page!</h1>
</body>
</html>


在这个结构的顶部有一个document,也称为根元素,它包含另一个元素:htmlhtml元素包含一个head,而 head 又有一个title。 然后body 包含一个h1。 每个 HTML 元素都由特定类型(也称为接口)表示,并且可能包含文本或其他嵌套元素:

document (HTMLDocument)
  |
  | --> html (HTMLHtmlElement)
          |  
          | --> head (HtmlHeadElement)
          |       |
          |       | --> title (HtmlTitleElement)
          |                | --> text: "A super simple title!"
          |
          | --> body (HtmlBodyElement)
          |       |
          |       | --> h1 (HTMLHeadingElement)
          |              | --> text: "A super simple web page!"


每个HTML元素都来自Element,但其中很大一部分都是专用的。 咱们可以检查原型以查找元素所属的 “种类”。 例如,h1元素是HTMLHeadingElement

document.querySelector('h1').__proto__

// Output: HTMLHeadingElement


HTMLHeadingElement则是HTMLElement的后代:

document.querySelector('h1').__proto__.__proto__

// Output: HTMLElement


此时(特别是初学者)可能会对 documentwindow 之间的区别产生一些混淆。接下来看看它们有何不同!

document 和 window 之间的区别

简单来说,documentwindow的一个对象属性。window 对象表示浏览器中打开的窗口。如果文档包含框架(frameiframe 标签),浏览器会为 HTML 文档创建一个 window 对象,并为每个框架创建一个额外的 window 对象。所有的全局函数和对象都属于 window 对象的属性和方法。

区别:

  1. window 指窗体。document指页面。documentwindow的一个子对象。
  2. 用户不能改变 document.location(因为这是当前显示文档的位置)。但是, 可以改变window.location (用其它文档取代当前文档)window.location本身也是一个对象, 而document.location不是对象。

document 接口有许多实用方法,比如querySelector(),它是用于查找给定页面内 HTML 元素的方法:

document.querySelector('h1');

window表示当前的浏览器,下面代码与上面等价:

window.document.querySelector('h1');

当然,更常见的是用第一种方式。

window 是一个全局对象,可以从浏览器中运行的任何 JS 代码直接访问。 window暴露了很多属性和方法,如:

window.alert('Hello world'); // Shows an alert
window.setTimeout(callback, 3000); // Delay execution
window.fetch(someUrl); // make XHR requests
window.open(); // Opens a new tab
window.location; // Browser location
window.history; // Browser history
window.navigator; // The actual user agent
window.document; // The current page

因为这些属性和方法也是全局的,所以也可以这样访问它们

alert('Hello world'); // Shows an alert
setTimeout(callback, 3000); // Delay execution
fetch(someUrl); // make XHR requests
open(); // Opens a new tab
location; // Browser location
history; // Browser history
navigator; // The actual user agent
document;// The current page

其中有些咱们都已经很熟悉了,如setTimeout() 的方法。 例如,当咱们想要得知当前用户的浏览器语言时,window.navigator就非常有用:

if (window.navigator) {
  var lang = window.navigator.language;
  if (lang === "en-US") {
    // show something
  }

  if (lang === "it-IT") {
    // show something else
  }
}

DOM 常用方法

获取节点

// 通过id号来获取元素,返回一个元素对象
document.getElementById(idName) 
      
// 通过name属性获取id号,返回元素对象数组 
document.getElementsByName(name)  
   
// 通过class来获取元素,返回元素对象数组
document.getElementsByClassName(className)   

// 通过标签名获取元素,返回元素对象数组
document.getElementsByTagName(tagName)       

获取 / 设置元素的属性值:

// 括号传入属性名,返回对应属性的属性值
element.getAttribute(attributeName)

// 传入属性名及设置的值
element.setAttribute(attributeName,attributeValue)

创建节点 Node

// 创建一个html元素,这里以创建h3元素为例
document.createElement("h3")

// 创建一个文本节点;
document.createTextNode(String);

// 创建一个属性节点,这里以创建class属性为例
document.createAttribute("class");

增添节点

// 往element内部最后面添加一个节点,参数是节点类型
element.appendChild(Node);

// 在element内部的中在existingNode前面插入newNode
elelment.insertBefore(newNode,existingNode); 

删除节点

//删除当前节点下指定的子节点,删除成功返回该被删除的节点,否则返回null
element.removeChild(Node)

DOM 常用属性

获取当前元素的父节点

// 返回当前元素的父节点对象
element.parentNode

获取当前元素的子节点

// 返回当前元素所有子元素节点对象,只返回HTML节点
element.chlidren

// 返回当前元素多有子节点,包括文本,HTML,属性节点。(回车也会当做一个节点)
element.chilidNodes

// 返回当前元素的第一个子节点对象
element.firstChild

// 返回当前元素的最后一个子节点对象
element.lastChild

获取当前元素的同级元素

// 返回当前元素的下一个同级元素 没有就返回null
element.nextSibling

// 返回当前元素上一个同级元素 没有就返回 null
element.previousSibling

获取当前元素的文本

// 返回元素的所有文本,包括html代码
element.innerHTML

// 返回当前元素的自身及子代所有文本值,只是文本内容,不包括html代码
element.innerText

获取当前节点的节点类型

// 返回节点的类型,数字形式(1-12)
// 常见几个1:元素节点,2:属性节点,3:文本节点。
node.nodeType   

设置样式

// 设置元素的样式时使用style
element.style.color=“#eea”;

DOM 操作

DOM 中的每个 HTML 元素也是一个节点,可以像这样查找节点:

document.querySelector('h1').nodeType;

上面会返回1,它是Element类型的节点的标识符,还可以检查节点名称:

document.querySelector('h1').nodeName;

"H1"

上面的示例返回大写的节点名。但是需要理解的最重要的概念是,咱们主要使用 DOM 中的两种类型的节点:

  • 元素节点
  • 文本节点

创建元素节点,可以通过 createElement方法:

var heading = document.createElement('h1');

创建文本节点,可能通过 createTextNode 方法:

var text = document.createTextNode('Hello world');

接着将两个节点组合在一起,然后添加到 body 上:

var heading = document.createElement('h1');
var text = document.createTextNoe('Hello world');
heading.appendChild(text);
document.body.appendChild(heading)

在学习 Dom 操作时候,这些方法需要牢记并熟练使用的。

目前像咱们用这种方式创建和操作元素,是属于命令式 DOM 操作。现代前端库通过支持声明性方法来解决这个问题,如 JQuery, 咱们可以声明需要什么 HTML 元素,其它就由库来完成。

DOM 操作和 jQuery

大部分可能会想,咱们直接使用 JQ 不就行了,为啥还要用如createElement这些原生的方法,多费劲。

请注意 jQuery 正在渐渐消失。Bootstrap 5 将把它从依赖项中删除,还有很多项目也在删除它。这背后有一个合理的原因: 原生 DOM API 提供了大量像 JQ 这样操作 DOM 的简便方法,足以替代 jQuery 一些常用的 DOM 操作。

如果只是想进行简单的交互和操作,请使用普通的 JS。咱们甚至可以创建自己的迷你框架来抽象最常见的操作: 创建元素、追加、创建文本。

总结

DOM 是浏览器创建并保留在内存中的网页的虚拟副本。创建、修改、删除 HTML 元素,这些属于 “DOM 操作”。在过去即使对于更简单的任务,咱们也要依赖于 jQuery,但今天原生 API 已经互相兼容并且足够成熟足以替代 jQuery 了。

jQuery 不会很快消失,但是每个 JS 开发人员都必须知道如何使用原生 API 操作 DOM。这样做有很多原因,额外的库增加了 JS 应用程序的加载时间和大小,更不用说 DOM 操作在技术面试也经常出现。

操作 DOM 最常用的方法是 document.createElement() 用于创建新的 HTML 元素,document.createTextNode() 用于在 DOM 内创建文本节点。需要注意的是 .appendChild() 用于将新的 HTML 元素或文本节点附加到现有元素。

虽然很好的了解本机 API 是很好的,但是现代前端库也提供了无可置疑的好处。尽管用 “原生” JS 去构建大型 JS 程序确实是可行的,但有时 Angular、React、Vue 可以提供很多帮助。仅使用 JavaScript 来处理更简单的原型和中小型应用也是明智之举。

原文:https://www.valentinog.com/bl...

代码部署后可能存在的 BUG 没法实时知道,事后为了解决这些 BUG,花了大量的时间进行 log 调试,这边顺便给大家推荐一个好用的 BUG 监控工具 Fundebug

原文地址 segmentfault.com

浏览 (966)
点赞
收藏
评论