客户端JavaScript的存在使得静态的HTML文档变成了交互式的Web应用。脚本化Web页面内容是JavaScript的核心目标。本章——本书中最重要的章节之一——阐述了他是如何做到的。
每个Window对象有一个document属性引用了Document对象。Document对象表示窗口的内容。Document对象并非独立的,他是一个巨大的API中的核心对象,叫做文档对象模型(Document Object Model,DOM),它代表和操作文档的内容。
DOM概览
文档对象模型(DOM)是表示和操作HTML和XML文档内容的基础API。 (下面应该是少了一个封闭的p标签)
每一个方框是文档的一个节点,它表示一个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 。。。
其中属性nodeType:9表示document节点,1表示Element节点,3表示Text节点。
例子:
<html><head><title>Test</title></head><body>test</body></html> (注意这是一行,中间没有换行及空格)
下面两行代码得到的结果是一样的
document.childNodes[0].childNodes[1]
document.firstChild.firstChild.nextSibling
第一个子节点下面的第二个子节点就是<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节点。
Element对象的其他属性:firstElementChild(类似firstChild,但只代表子Element)。。。
属性
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请求类型
注意,可以用一些方法来查询,设置,删除一些属性。
数据集属性
在HTML5文档中,任意“data-”为前缀的小写的属性名字都是合法的。这些“数据集属性”将不会对元素的表现产生影响,他们定义了一种标准的,附加额外数据的方法,并不是在文档合法性上做出让步。
HTML5还在Element对象上定义了dataset属性。该属性指代一个对象,他的各个属性对应于去掉前缀的data-属性。因此dataset.x应该保存data-x属性的值。
连带字符的属性对应于驼峰命名法属性名:data-test-id属性就变成dataset.testId属性
作为Attr节点的属性
还有一种使用Element的属性的方法。Node类型定义了attributes属性。attributes属性是只读的类数组对象,他表示元素的所有属性。类似NodeList,attributes对象也是实时的。
当索引attributes对象时得到的值是Attr对象。Attr对象一类特殊的Node,但从不会像Node一样去用。Attr的name和value属性返回该属性的名字和值。
元素的内容
1.HTML字符串(包括标签)
2.纯文本字符串
3.节点(可能包含多个)
创建,插入和删除节点
创建新的Element节点可以使用Document对象的createElement()方法
Text节点用类似的方法创建:document.createTextNode("test");
插入节点可以用Node的方法:appendchild()和insertBefore()
删除节点:removeChild() 在父节点上调用
节点替换:replaceChild() 在父节点上调用
文档和元素的几何形状和滚动
Web应用程序可以将文档看作是元素的树,并且不用关心在屏幕上这些元素是如何渲染的。
判定一个元素的尺寸和位置最简单的方法是调用它的getBoudingClientRect()方法。(不是实时的)
如果想查询内联元素每个独立的矩形,调用getClientRects()方法来获得一个只读的类数组对象,他的每个元素类似于getBoudingClientRect()返回的矩形对象。(不是实时的)
Document属性
Document的属性有body,documentElement和forms等这些特殊的文档元素。还有其他有趣的属性:
cookie,doman,lastModified,location,referrer,title,URL
referrer是这些属性中最有趣的属性之一:他包含用户链到当前文档的上一个文档的URL。