JavaScript权威指南(个人笔记):(七)脚本化文档
客户端JavaScript的存在使得静态的HTML文档变成了交互式的Web应用。脚本化Web页面内容是JavaScript的核心目标。本章——本书中最重要的章节之一——阐述了他是如何做到的。
每个Window对象有一个document属性引用了Document对象。Document对象表示窗口的内容。Document对象并非独立的,他是一个巨大的API中的核心对象,叫做文档对象模型(Document Object Model,DOM),它代表和操作文档的内容。

DOM概览
文档对象模型(DOM)是表示和操作HTML和XML文档内容的基础API。
HTML文档的树状结构包含表示HTML标签或元素(如<body> <p>)和表示文本字符串的节点,它也可能包含表示HTML注释的节点(文档树)

上图中的每一个方框是文档的一个节点,它表示一个Node对象。
树形的根部是Document节点,它代表整个文档。代表HTML元素的节点是Element节点,代表文本的节点是Text节点。Document,Element和Text是Node的子类。

选取文档元素
查询文档的一个或多个元素有如下方法:
1. id属性 document.getElementById()
2. name属性 document.getElementsByName() 返回一个NodeList对象
3. 标签名字 document.getElementsByTagName() 返回一个NodeList对象
4. CSS类 document.getElementsByClassName() 返回一个NodeList对象
5. CSS选择器 document.querySelectorAll() 返回一个NodeList对象(这个不是实时的,上面的是)
注意:这个几个可以连在一起用!!!
通过名字选取元素
HTML的name属性最初打算为表单元素分配名字,在表单数据提交到服务器时使用该属性的值。
类似id属性,name是给元素分配名字,但是区别于id,name属性的值不是必须唯一:多个元素可能有同样的名字,在表单中,单选和复选按钮通常是这种情况。
而且,name属性只在少数HTML元素中有效,包括表单,表单元素等
document.getElementsByName() 返回一个NodeList对象,类似一个包含若干Element对象的只读数组。
为某些HTML元素设置name属性值将自动为Window对象创建对应的属性,对Document对象也类似。为<form>等元素色设置name属性值,即在Document对象中创建以此name属性值为名字的属性(当然,假设此文档还没有该名字的属性)。
如果给定的名字只有一个元素,自动创建的文档属性对应的该值是元素本身。如果有多个元素,该文档属性的值是一个NodeList对象,它表现为一个包含这些元素的数组。这就意味着有些元素可以作为Document属性仅通过名字来选取:
<form action="" name="hello"></form>
let form = document.hello // 得到Element对象
注意:只针对部分元素有效!

作为节点树的文档
Document对象、它的Element对象和文档中表示文本的Text对象都是Node对象。
Node对象的属性如下:
parentNode 该节点的父节点
childNodes 该节点的子节点 (NodeList对象)
fistChild,lastChild 该节点的子节点中的第一个和最后一个
previousSibling,nextSibling 该节点的兄弟节点节点的前一个和下一个
nodeType 9表示document节点,1表示Element节点,3表示Text节点。
nodeValue Text节点或Comment节点的内容
nodeName 元素的标签名,以大写形式表示
例子:
下面两行代码得到的结果是一样的
document.childNodes[0].childNodes[1]
document.firstChild.firstChild.nextSibling
例子:
<html><head><title>Test</title></head><body>test</body></html> (注意这是写成一行的代码,中间没有换行及空格)
第一个子节点下面的第二个子节点就是<body>元素,它的nodeType为1,nodeName为“BODY”。
注意:如果修改了文档,在<html>和<head>标签之间插入新的一行,那么表示该行的Text节点就是文档的第一个子节点下面的子节点,并且<head>元素就是第二个子节点的,而不是<body>元素了。
作为元素树的文档
当将主要的兴趣点集中在文档中的元素上而非他们之间的文本(和他们之间的的空白)上时,我们可以使用另一个更有用的API。他将文档看作是Element对象树,忽略部分文档:Text和Comment节点。
该API的第一部分是Element对象的children属性!!!
类似childNodes,它也是一个NodeList对象,但不同的是children列表只包含Element对象。
注意:Text和Comment节点没有children属性。它意味着上述Node.parentNode属性不可能返回Text和Comment节点。任何Element对象的parentNode总是另一个Element,或者追溯到树根的Document节点。
基于元素的文档遍历API的第二部分是Element属性,类似Node对象的子属性和兄弟属性:
firstElementChild,lastElementChild
previousElementSibling,nextElementSibling
childElementCount 子元素的数量。返回的值和children.length值相等。
属性
HTML元素由一个标签和一组成为属性(attribute)的名值对组成。例如,<a>元素定义了一个超链接,它的href属性值作为链接的目的地址。
HTML元素的属性值在代表这些元素的HTMLElement对象的属性(property)中是可用的。
HTML属性作为Element的属性
表示HTML文档元素的HTMLElement对象定义了读写属性,他们映射了元素的HTML属性。
例子:可以为一个<form>元素设置表单提交的属性
let f = document.forms[0]; // 文档中第一个<form>
f.action = "http://test.php"; // 设置提交的URL
f.method= "POST"; // HTTP请求类型
注意:如果属性名包含不止一个单词,则将除了第一个单词以外的的单词的首字母大写
获取和设置非标准HTML属性
Element类型定义了getAttribute()和setAttribute()方法来查询和设置非标准的HTML属性,如:
var image = document.images[0];
var width = parseInt(image.getAttribute("WIDTH"));
image.setAttribute("class", "thumbnail");
Element类型还定义了两个相关的方法,hasAttribute()和removeAttribute(),他们用来检测命名属性是否存在和完全删除属性。
数据集属性
在HTML5文档中,任意“data-”为前缀的小写的属性名字都是合法的。这些“数据集属性”将不会对元素的表现产生影响,他们定义了一种标准的,附加额外数据的方法,并不是在文档合法性上做出让步。
HTML5还在Element对象上定义了dataset属性。该属性指代一个对象,他的各个属性对应于去掉前缀的data-属性。因此dataset.x应该保存data-x属性的值。
连带字符的属性对应于驼峰命名法属性名:data-test-id属性就变成dataset.testId属性
作为Attr节点的属性
Node类型定义了attributes属性。attributes属性是只读的类数组对象,他表示元素的所有属性。类似NodeList,attributes对象也是实时的。它可以用数字索引访问,这意味着可以枚举元素的所有属性。并且,它可以用属性名索引:
document.body.attributes.bgcolor // <body>元素的bgcolor属性
当索引attributes对象时得到的值是Attr对象。Attr对象一类特殊的Node,但从不会像Node一样去用。Attr的name和value属性返回该属性的名字和值。
元素的内容
例子:<p>This is a <i>simple</i> document</p>
<p>元素的“内容”是什么?回答这个问题也许有3个方法:
1.THML字符串 "This is a <i>simple</i> document"
2.纯文本字符串 "This is a simple document"
3.一个Text节点,一个包含了一个Text子节点的Element节点,另一个Text节点
作为HTML的元素内容 可以使用innerHTML属性获取
作为纯文本的元素内容 可以使用textContent 或 innerText属性获取
创建,插入和删除节点
创建新的Element节点可以使用:document.createElement()
Text节点用类似的方法创建:document.createTextNode("test"); 创建并返回一个代表指定文本的新的Text节点
插入节点可以用Node的方法:appendchild(),insertBefore()(这个接受两个参数)
删除节点:removeChild()(在父节点上调用)在文档中删除n节点,代码可以这样写:
n.parentNode.removeChild(n);
节点替换:replaceChild()(在父节点上调用)
文档和元素的几何形状和滚动
无论在何种情况下,当讨论元素的位置时,必须弄清楚所使用的坐标是文档坐标还是视口坐标。(注意,视口坐标有时也叫做窗口坐标)

判定一个元素的尺寸和位置最简单的方法是调用它的getBoudingClientRect()方法。(不是实时的)
任何HTML元素的只读属性offsetWidth和offsetHeight以CSS像素返回他的屏幕尺寸。
所有HTML元素拥有offsetLeft和offsetTop属性来返回元素的X和Y坐标。

Document属性
Document的属性有body,documentElement和forms等这些特殊的文档元素。还有其他有趣的属性:
cookie,doman,lastModified,location,referrer,title,URL
referrer是这些属性中最有趣的属性之一:他包含用户链到当前文档的上一个文档的URL。
补充:
Document对象是文档树的根节点,DocumentElement属性是文档的根元素,比如HTML文档的<html>元素。
在支持HTML5中Element对象的classList属性的浏览器中,它是一个DOMTokenList,这可能是你唯一经常使用的DOMTokenList。
属性:length 方法:add, remove,toggle
tagName
当前元素的标签名。对HTML文档来说,无论文档源代码中标签名的大小写情况如何,总是返回大写的形式,所以,一个<p>元素的tagName属性值为“P”
浙公网安备 33010602011771号