Js高程-DOM
Js高程-DOMnode类型节点查询操纵节点其他方法Document 类型文档子节点文档信息定位元素Element 类型HTML元素属性相关方法1. 获取属性2. 设置属性3. 创建元素4. 元素后代Text 类型DOM扩展——Selectors APIHTML5CSS类扩展焦点管理
node类型
文档对象模型 DOM(document object model)表示由多层节点构成的文档,通过它开发者可以添加、删除和修改页面的各个部分。
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
<img src="C:\Users\peekapoo\AppData\Roaming\Typora\typora-user-images\image-20210131205513995.png" alt="image-20210131205513995" style="zoom:80%;" />
document
节点为每个文档的根节点。<html>
为文档元素,指的是文档最外层的元素。
HTML中每段标记都可以表示为树形结构中的一个node,node共有12种节点类型。
1 ELEMENT_NODE
2 ATTRIBUTE_NODE
3 TEXT_NODE
4 CDATA_SECTION_NODE
9 DOCUMENT_NODE
...
节点查询
可用 someNode.nodeType === 1
来判断是否是ELEMENT_NODE类型。
可用 someNode.nodeName
来获得节点的标签名。
可用 someNode.childNodes
来获取 NodeList
实例,
<img src="C:\Users\peekapoo\AppData\Roaming\Typora\typora-user-images\image-20210131211625241.png" alt="image-20210131211625241" style="zoom:80%;" />
parentNode
属性指向DOM树的父元素,previousSibling
和 nextSibling
可用在 childNodes 的兄弟节点间导航。
firstChild
和 lastChild
分别指向父节点的第一个和最后一个子节点。也就是 someNode.firstNode === someNode.childNodes[0]
<img src="C:\Users\peekapoo\AppData\Roaming\Typora\typora-user-images\image-20210131212600535.png" alt="image-20210131212600535" style="zoom:80%;" />
操纵节点
-
appendChild()
,用于在 childNodes 列表末尾添加节点,同时会更新相关的关系指针,比如上一节中的一些只读属性。-
let returnedNode = someNode.appendChild(newNode);
该方法返回新添加的节点。 -
如果该新节点已经存在,则使用
appengChild()
后,这个节点会被转移到新位置,即被挪到父元素的最后一个子节点处。
-
-
insertBefore()
,用于将节点放到 childNodes 列表中特定位置,插入的 newNode 会被插入参照节点的前一个兄弟节点处。-
returnedNode = someNode.inserBefore(newNode, null)
效果等同于appendChild()
-
-
replaceChild()
,方法接收两个参数,要插入的节点和要替换的节点。被替换的节点会被该方法返回,并且被从DOM树种完全移出,要插入的节点取而代之,所有的关系指针都会从被替换节点复制过来。 -
removeChild()
,可用于移除节点,方法会返回被移除的节点。
以上四种方法都是基于父节点来操作子元素,若用于某些不支持子节点的节点,则会抛出错误。
其他方法
-
cloneNode()
会返回与调用它的节点一模一样的节点。复制返回的节点尚未指定父节点,可成为孤儿节点-
在传入 true 参数时,会进行深复制,即复制节点及整个子DOM树
-
传入 false 参数时,则只会复制调用该方法的节点。
-
-
normalize()
用于处理DOM文档子树中的文本节点。由于解析器实现的差异或 DOM 操作等原因,可能会出现并不包含文本的文本节点,或者文本节点之间互为同胞关系。在节点上调用 normalize()方法会检测这个节点的所有后代,从中搜索上述两种情形。如果发现空文本节点,则将其删除;如果两个同胞节点是相邻的,则将其合并为一个文本节点。
Document 类型
浏览器中,文档对象 document 是 HTMLDocument 的实例,表示整个 HTML 页面。document 是 window 对象的属性,因此是一个全局对象。所以可用直接在 console 中使用 document 属性。
<img src="C:\Users\peekapoo\AppData\Roaming\Typora\typora-user-images\image-20210131221253036.png" alt="image-20210131221253036" style="zoom:80%;" />
文档子节点
-
document.documentElement
指向<html>
元素。 -
document.body
指向<body>
元素。 -
document.doctype
指向<!doctype>
标签
操作节点的三个方法不在 document 类型上使用,这些文档子节点都是只读的。
文档信息
// 读取文档标题
let originalTitle = document.title;
// 修改文档标题,可用在浏览器上实时显示修改,但是不会将修改写入源文件
document.title = "New page title";
// 取得完整的 URL
let url = document.URL;
// 取得域名
let domain = document.domain;
// 取得来源
let referrer = document.referrer;
URL,domain,referrer都可用在请求的HTTP头部信息中【用得不多,先略过】
定位元素
获取某个元素或某组元素的引用:getElementById()
和 getElementsByTagName()
和 getElementsByName()
-
getElementById()
返回在文档中出现的符合条件的第一个元素 -
getElementsByTagName()
返回包含零个或多个元素的 NodeList 。在HTML文档中,该方法返回一个 HTMLCollection 对象-
HTMLCollection 相比 NodeList ,多了一个 namedItem() 方法,通过过标签的 name 属性取得某一项的引用。
-
-
getElementsByName()
会返回具有给定 name 属性的所有元素。常用于单选按钮
还有一些特殊集合,例如获取所有带href的 <a>
元素的 document.links
Element 类型
nodeType === 1 nodeName 为元素的标签名 nodeValue 为null
子节点可以是 Element Text Comment ProcessingInstruction CDATASection EntityReference
tagName === nodeName
返回元素的标签名。但是 div.tagName
返回的是 “DIV“,是大写,在判断时最好转成小写形式:element.tagName.toLowerCase()
所有 HTML 元素都通过 HTMLElement 类型表示,它有这些属性:
id //元素在文档内唯一标识符
className //相当于 class 属性,用于指定元素的 CSS 类
//等……
let div = document.getElementById("myDiv");
alert(div.id); // "myDiv"
div.id = "someOtherId" //可修改元素的属性,但不会修改源文件
<img src="C:\Users\peekapoo\AppData\Roaming\Typora\typora-user-images\image-20210201173221156.png" alt="image-20210201173221156" style="zoom:80%;" />
HTML元素不止有 div
,还有很多 a 标签,h1~h6标签,strong标签,它们都是 HTMLElement 或其子类型的实例。具体类型可在p415页查询。
属性相关方法
与属性相关的 DOM 方法 主要有 3 个:getAttribute()
、setAttribute()
和 removeAttribute()
。
1. 获取属性
let div = document.getElementById("myDiv");
alert(div.getAttribute("id")); // "myDiv"
alert(div.getAttribute("class")); // "bd"
这里要传"class"而非"className"(className 是作为对象属性时才那么拼写的)。
如果给定的属性不存在,则 getAttribute()
返回 null。属性不只是HTML语言定义的属性,也可以自定义的属性,但是由于HTML不区分大小写,要注意不要产生冲突。
但是,除了自定义属性外的属性,其他工人的属性可用直接通过DOM对象来访问,其中style
和事件处理程序,使用这两种方法返回的内容不一样。
-
在使用
getAttribute()
访问 style 属性时,返回的 是 CSS 字符串。而在通过 DOM 对象的属性访问时,style 属性返回的是一个(CSSStyleDeclaration) 对象。 -
使用
getAttribute()
访问事件属性, 则返回的是字符串形式的源代码。而通过 DOM 对象的属性访问事件属性时返回的则是一个 JavaScript 函数。
2. 设置属性
setAttribute()
,这个方法接收两个参数:要设置的属性名 和属性的值。如果属性已经存在,则会以指定的值替换原来的值;如果属性不存在, 则会以指定的值创建该属性。
setAttribute()
适用于 HTML 属性,也适用于自定义属性。另外,使用该方法 设置的属性名会规范为小写形式,因此"ID"会变成"id"。
3. 创建元素
可以使用 document.createElement()
方法创建新元素。这个方法接收一个参数,即要创建元素的标签名。
let div = document.createElement("div");
div.id = "myNewDiv";
div.className = "box";
document.body.appendChild(div);
4. 元素后代
<ul id="myList">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
在解析以上代码时,<ul>元素会包含 7 个子元素,其中 3 个是<li>元素,还有 4 个 Text 节点(表示<li>元素周围的空格)。【也就是换行符……】
for (let i = 0, len = element.childNodes.length; i < len; ++i) {
if (element.childNodes[i].nodeType == 1) {
// 执行某个操作
}
}
//以上代码会遍历某个元素的子节点,并且只在 nodeType 等于 1(即 Element 节点)时执行某个操作。
Text 类型
Text 节点由 Text 类型表示,包含按字面解释的纯文本,也可能包含转义后的 HTML 字符。
nodeType === 3 nodeName 为'#text'
nodeValue 为节点中包含的文本
不支持子节点
textNode.nodeValue === textNode.data
![image-20210201180729652](C:\Users\peekapoo\AppData\Roaming\Typora\typora-user-images\image-20210201180729652.png)
DOM扩展——Selectors API
Selectors API Level 1 的核心是两个方法:querySelector()
和 querySelectorAll()
。
在兼容浏览器中,Document 类型和 Element 类型的实例上都会暴露这两个方法。
querySelector()
:返回匹配该模式的第一个后代元素
-
在 Document 上使用该方法时,会从文档元素开始搜索;
-
在 Element 上使用该方法时,则只会从当前元素的后代中查询。
querySelectorAll()
:会返回 所有匹配的节点
HTML5
CSS类扩展
-
getElementsByClassName()
是 HTML5 新增的一个方法
焦点管理
HTML5 增加了辅助 DOM 焦点管理的功能。
-
document.activeElement
,始终包含当前拥 有焦点的 DOM 元素。默认情况下,在页面刚加载完之后,该属性会设置为document.body
。
let button = document.getElementById("myButton");
button.focus();
console.log(document.activeElement === button); // true
-
document.hasFocus()
方法,该方法返回布尔值,表示文档是否拥有焦点
let button = document.getElementById("myButton");
button.focus();
console.log(document.hasFocus()); // true