JS(10)——DOM(文档对象模型)

1. 概念

DOM是针对HTML 和XML 文档的一个API(应用程序编程接口)。DOM描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。

DOM 可以将任何HTML 或XML 文档描绘成一个由多层节点构成的结构。节点分为几种不同的类型,每种类型分别表示文档中不同的信息及(或)标记。每个节点都拥有各自的特点、数据和方法,另外也与其他节点存在某种关系。节点之间的关系构成了层次,而所有页面标记则表现为一个以特定节点为根节点的树形结构。

注意IE 中的所有DOM 对象都是以COM 对象的形式实现的。这意味着IE 中的DOM 对象与原生JavaScript 对象的行为或活动特点并不一致。


2. Node类型
2.1 概念

JavaScript中的所有节点类型都继承自Node 类型,因此所有节点类型都共享着相同的基本属性和方法。每个节点都有一个nodeType 属性,用于表明节点的类型。节点类型由在Node 类型中定义的下列12 个数值常量来表示,任何节点类型必居其一:

 Node.ELEMENT_NODE(1);

 Node.ATTRIBUTE_NODE(2);

 Node.TEXT_NODE(3);

 Node.CDATA_SECTION_NODE(4);

 Node.ENTITY_REFERENCE_NODE(5);

 Node.ENTITY_NODE(6);

 Node.PROCESSING_INSTRUCTION_NODE(7);

 Node.COMMENT_NODE(8);

 Node.DOCUMENT_NODE(9);

 Node.DOCUMENT_TYPE_NODE(10);

 Node.DOCUMENT_FRAGMENT_NODE(11);

 Node.NOTATION_NODE(12)。

通过比较上面这些常量,可以很容易地确定节点的类型,例如:

if (someNode.nodeType == Node.ELEMENT_NODE){ //在IE 中无效 }

2.2 常用的Node方法

1、childNodes

每个节点都有一个childNodes 属性,其中保存着一个NodeList 对象。NodeList 是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点。请注意,虽然可以通过方括号语法来访问NodeList 的值,而且这个对象也有length 属性,但它并不是Array 的实例

var firstChild = someNode.childNodes[0];

var secondChild = someNode.childNodes.item(1);

var count = someNode.childNodes.length;

var next=someNode.nextSibling;

var previous=someNode.previousSibling;//获得同胞节点

2appendChild

var input=document.createElement('input');
input.appendChild(newNode);//  相当于$("input").append(roomEle);

注意:如果传入到appendChild()中的节点已经是文档的一部分了,那结果就是将该节点从原来的位置转移到新位置

3、insertBefore

//插入后成为第一个子节点
var returnedNode = someNode.insertBefore(newNode, someNode.firstChild);

注意:如果参照节点是null,则insertBefore()appendChild()执行相同的操作

4replaceChild()

 replaceChild()方法接受的两个参数是:要插入的节点和要替换的节点。插入一个节点时,该节点的所有关系指针都会从被它替换的节点复制过来。尽管从技术上讲,被替换的节点仍然还在文档中,但它在文档中已经没有了自己的位置。

//替换第一个子节点
var returnedNode = someNode.replaceChild(newNode, someNode.firstChild);

5 removeChild()

//移除第一个子节点, 被移除的节点将成为方法的返回值。
var formerFirstChild = someNode.removeChild(someNode.firstChild);

6cloneNode()

用于创建调用这个方法的节点的一个完全相同的副本。cloneNode()方法接受一个布尔值参数,表示是否执行深复制。在参数为true的情况下,执行深复制,也就是复制节点及其整个子节点树;在参数为false 的情况下,执行浅复制,即只复制节点本身。复制后返回的节点副本属于文档所有,但并没有为它指定父节点。cloneNode()方法不会复制添加到DOM 节点中的JavaScript 属性,例如事件处理程序等。这个方法只复制特性、(在明确指定的情况下也复制)子节点,其他一切都不会复制相当于

var ele = $("#template").clone(true);

3. Document类型
3.1 常用document对象属性
var html = document.documentElement; //取得对<html>的引用

var body = document.body; //取得对<body>的引用

var originalTitle = document.title; //取得文档标题

var url = document.URL; //取得完整的URL

var domain = document.domain;//取得域名

var referrer = document.referrer; //取得来源页面的URL

3.2 document对象特殊集合

除了属性和方法,document 对象还有一些特殊的集合。这些集合都是HTMLCollection 对象,为访问文档常用的部分提供了快捷方式,包括:

document.anchors,包含文档中所有带name 特性的<a>元素;

document.forms,包含文档中所有的<form>元素,与document.getElementsByTagName("form")得到的结果相同;

document.images,包含文档中所有的<img>元素,与document.getElementsByTagName("img")得到的结果相同;

document.links,包含文档中所有带href 特性的<a>元素。

这些对象都可以通过.length来获得这些集合的长度,通过下标来获得相应的元素,如:

var id=document.links[0].id;//获得第一个<a>标签的id属性
var length=document.images.length;

3.3 document对象方法

getElementById() --返回对拥有指定 id 的第一个对象的引用。

getElementsByName()--返回带有指定名称的对象集合。

getElementsByTagName()--返回带有指定标签名的对象集合。

open()--打开一个流,以收集来自任何 document.write() document.writeln() 方法的输出。

close()--关闭用 document.open() 方法打开的输出流,并显示选定的数据。

write()--向文档写 HTML 表达式 或 JavaScript 代码。

writeln()--等同于 write() 方法,不同的是在每个表达式之后写一个换行符。


3.4 write()writeln()方法

使用write()writeln()方法动态地包含外部资源,例如JavaScript文件等。在包含JavaScript文件时,必须注意不能像下面的例子那样直接包含字符串"</script>",因为这会导致该字符串被解释为脚本块的结束,它后面的代码将无法执行。

<html>
<head>
<title>document.write() Example 2</title>
</head>
<body>
    <script type="text/javascript">
        document.write("<script type=\"text/javascript\" src=\"file.js\">" +"</script>");
    </script>

</body>
</html>

即使这个文件看起来没错,但字符串"</script>"将被解释为与外部的<script>标签匹配,结果文本");将会出现在页面中。为避免这个问题,只需加入转义字符\即可;解决方案如下

<html>
<head>
<title>document.write() Example 3</title>
</head>
<body>
<script type="text/javascript">
    document.write("<script type=\"text/javascript\" src=\"file.js\">" +"<\/script>");
</script>
</body>
</html>

4. Element类型

1getAttribute()

var div = document.getElementById("myDiv");
alert(div.getAttribute("id")); //"myDiv"
alert(div.getAttribute("class")); //"bd"

通过getAttribute()方法也可以取得自定义特性,如

<div id="myDiv" my_special_attribute="hello!"></div>
var value = div.getAttribute("my_special_attribute");

特性的名称是不区分大小写的,即"ID"和"id"代表的都是同一个特性。另外也要注意,根据HTML5 规范,自定义特性应该加上data-前缀以便验证。

注意:公认Attribute(如idclassname)在该元素的DOM对象中也将存在对应的属性。不过,自定义特性my_special_attribute在Safari、Opera、Chrome 及Firefox 中是不存在的;但IE却会为自定义特性也创建属性,如下面的例子所示:

alert(div.id); //"myDiv"
alert(div.my_special_attribute); //undefined(IE 除外)
alert(div.align); //"left"

有两类特殊的特性,它们虽然有对应的属性名,但属性的值与通过getAttribute()返回的值并不相同。第一类特性就是style,用于通过CSS 为元素指定样式。在通过getAttribute()访问时,返回的style 特性值中包含的是CSS 文本,而通过属性来访问它则会返回一个对象。由于style 属性是用于以编程方式访问元素样式的,因此并没有直接映射到style 特性。第二类与众不同的特性是onclick 这样的事件处理程序。当在元素上使用时,onclick 特性中包含的是JavaScript 代码,如果通过getAttribute()访问,则会返回相应代码的字符串。而在访问onclick 属性时,则会返回一个JavaScript 函数(如果未在元素中指定相应特性,则返回null)。这是因为onclick 及其他事件处理程序属性本身就应该被赋予函数值。由于存在这些差别,在通过JavaScript 以编程方式操DOM时,开发人员经常不使用getAttribute(),而是只使用对象的属性。只有在取得自定义特性值的情况下,才会使用getAttribute()方法。 

2setAttribute()

div.setAttribute("id", "someOtherId");
div.setAttribute("class", "ft");

等价于

div.id = "someOtherId";
div.class= "left";

等价于

$(“input”).attr("id","list");

注意:不能通过对象的属性来设置自定义的Attribute ,如

div.mycolor = "red";
alert(div.getAttribute("mycolor")); //null(IE 除外)

3document.createElement()

在IE 中可以以另一种方式使用createElement(),即为这个方法传入完整的元素标签,也可以包含属性,如下面的例子所示。

var div = document.createElement("<div id=\"myNewDiv\" class=\"box\"></div >");

这种方式有助于避开在IE7 及更早版本中动态创建元素的某些问题。


5. Text类型

1文本节点由Text 类型表示,包含的是可以照字面解释的纯文本内容。纯文本中可以包含转义后的HTML字符,但不能包含HTML 代码。即:小于号、大于号或引号都会像下面的例子一样被转义。

//输出结果是"Some <strong>other</strong> message"
div.firstChild.nodeValue = "Some <strong>other</strong> message";

可以通过nodeValue 属性或data 属性访问Text 节点中包含的文本,这两个属性中包含的值相

同。对nodeValue 的修改也会通过data反映出来,反之亦然。使用下列方法可以操作节点中的文本:

 appendData(text):将text 添加到节点的末尾。

 deleteData(offset, count):从offset 指定的位置开始删除count 个字符。

 insertData(offset, text):在offset 指定的位置插入text。

 replaceData(offset, count, text):用text 替换从offset 指定的位置开始到offset+count 为止处的文本。

 splitText(offset):从offset 指定的位置将当前文本节点分成两个文本节点。

 substringData(offset, count):提取从offset 指定的位置开始到offset+count 为止处的字符串。

除了这些方法之外,文本节点还有一个length 属性,保存着节点中字符的数目。而且,nodeValue.length 和data.length 中也保存着同样的值。在默认情况下,每个可以包含内容的元素最多只能有一个文本节点,而且必须确实有内容存在。例如:

<!-- 没有内容,也就没有文本节点 -->
<div></div>

<!-- 有空格,因而有一个文本节点 -->
<div> </div>

<!-- 有内容,因而有一个文本节点 -->
<div>Hello World!</div>
 

一般情况下,每个元素只有一个文本子节点。不过,在某些情况下也可能包含多个文本子节点,如下面的例子所示。

var element = document.createElement("div");
element.className = "message";

var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);

var anotherTextNode = document.createTextNode("Yippee!");
element.appendChild(anotherTextNode);

document.body.appendChild(element);

如果两个文本节点是相邻的同胞节点,那么这两个节点中的文本就会连起来显示,中间不会有空格。

2normalize()

如果在一个包含两个或多个文本节点的父元素上调用normalize()方法,则会将所有文本节点合并成一个节点,结果节点的nodeValue 等于将合并前每个文本节点的nodeValue 值拼接起来的值。例如:

var element = document.createElement("div");
element.className = "message";

var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);

var anotherTextNode = document.createTextNode("Yippee!");
element.appendChild(anotherTextNode);

document.body.appendChild(element);

alert(element.childNodes.length); //2

element.normalize();

alert(element.childNodes.length); //1
alert(element.firstChild.nodeValue); // "Hello world!Yippee!"

3splitText()

这个方法会将一个文本节点分成两个文本节点,即按照指定的位置分割nodeValue 值。原来的文本节点将包含从开始到指定位置之前的内容,新文本节点将包含剩下的文本。这个方法会返回一个新文本节点,该节点与原节点的parentNode 相同。例如:

var element = document.createElement("div");
element.className = "message";

var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);

document.body.appendChild(element);

var newNode = element.firstChild.splitText(5);
alert(element.firstChild.nodeValue); //"Hello"
alert(newNode.nodeValue); //" world!"

alert(element.childNodes.length); //

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值