wpf 类型style不支持直接内容?_10.1.3 Element类型

除了 Document 类型之外,Element 类型就要算是 Web 编程中最常用的类型了。Element 类型用 于表现 XML 或 HTML元素,提供了对元素标签名、子节点及特性的访问。Element 节点具有以下特征:

 nodeType 的值为 1;

 nodeName 的值为元素的标签名;

 nodeValue 的值为 null;

 parentNode 可能是 Document 或 Element;

 其子节点可能是 Element、Text、Comment、ProcessingInstruction、CDATASection 或 EntityReference。

要访问元素的标签名,可以使用 nodeName 属性,也可以使用 tagName 属性;这两个属性会返回相同的值(使用后者主要是为了清晰起见)。以下面的元素为例:

<div id="myDiv"></div>

可以像下面这样取得这个元素及其标签名:

var div = document.getElementById("myDiv");

alert(div.tagName); //"DIV"

alert(div.tagName == div.nodeName); //true

这里的元素标签名是 div,它拥有一个值为"myDiv"的 ID。可是,div.tagName 实际上输出的是 "DIV"而非"div"。在 HTML 中,标签名始终都以全部大写表示;而在 XML(有时候也包括 XHTML) 中,标签名则始终会与源代码中的保持一致。假如你不确定自己的脚本将会在 HTML 还是 XML 文档中 执行,最好是在比较之前将标签名转换为相同的大小写形式,如下面的例子所示:

if (element.tagName == "div"){ //不能这样比较,很容易出错!

//在此执行某些操作

}

if (element.tagName.toLowerCase() == "div"){ //这样最好(适用于任何文档)

//在此执行某些操作

}

这个例子展示了围绕 tagName 属性的两次比较操作。第一次比较非常容易出错,因为其代码在 HTML 文档中不管用。第二次比较将标签名转换成了全部小写,是我们推荐的做法,因为这种做法适用 于 HTML 文档,也适用于 XML 文档。

可以在任何浏览器中通过脚本访问 Element 类型的构造函数及原型,包括 IE8 及 之前版本。在 Safari 2 之前版本和 Opera 8 之前的版本中,不能访问 Element 类型的构造函数。

1. HTML 元素

所有 HTML 元素都由 HTMLElement 类型表示,不是直接通过这个类型,也是通过它的子类型来表 示。HTMLElement 类型直接继承自Element 并添加了一些属性。添加的这些属性分别对应于每个 HTML 元素中都存在的下列标准特性。

 id,元素在文档中的唯一标识符。

 title,有关元素的附加说明信息,一般通过工具提示条显示出来。

 lang,元素内容的语言代码,很少使用。

 dir,语言的方向,值为"ltr"(left-to-right,从左至右)或"rtl"(right-to-left,从右至左),

也很少使用。  className,与元素的class 特性对应,即为元素指定的CSS类。没有将这个属性命名为class, 是因为 class 是 ECMAScript 的保留字(有关保留字的信息,请参见第 1 章)。 上述这些属性都可以用来取得或修改相应的特性值。以下面的 HTML 元素为例:

<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div>

元素中指定的所有信息,都可以通过下列 JavaScript 代码取得:

var div = document.getElementById("myDiv");

alert(div.id); //"myDiv""

alert(div.className); //"bd"

alert(div.title); //"Body text"

alert(div.lang); //"en"

alert(div.dir); //"ltr"

当然,像下面这样通过为每个属性赋予新的值,也可以修改对应的每个特性:

div.id = "someOtherId";

div.className = "ft";

div.title = "Some other text";

div.lang = "fr";

div.dir ="rtl";

并不是对所有属性的修改都会在页面中直观地表现出来。对 id 或 lang 的修改对用户而言是透明 不可见的(假设没有基于它们的值设置的 CSS 样式),而对 title 的修改则只会在鼠标移动到这个元素 之上时才会显示出来。对 dir 的修改会在属性被重写的那一刻,立即影响页面中文本的左、右对齐方式。 修改 className 时,如果新类关联了与此前不同的 CSS 样式,那么就会立即应用新的样式。

前面提到过,所有 HTML 元素都是由 HTMLElement 或者其更具体的子类型来表示的。下表列出了 所有 HTML 元素以及与之关联的类型(以斜体印刷的元素表示已经不推荐使用了)。注意,表中的这些 类型在 Opera、Safari、Chrome 和 Firefox 中都可以通过 JavaScript 访问,但在 IE8 之前的版本中不能通 过 JavaScript 访问。

e084b4022f8679530b9ddf378695d243.png

084733a668d10ae11703c3368afca0c3.png

表中的每一种类型都有与之相关的特性和方法。本书将会讨论其中很多类型。

2. 取得特性

每个元素都有一或多个特性,这些特性的用途是给出相应元素或其内容的附加信息。操作特性的 DOM 方法主要有三个,分别是 getAttribute()、setAttribute()和 removeAttribute()。这三 个方法可以针对任何特性使用,包括那些以 HTMLElement 类型属性的形式定义的特性。来看下面的例子:

var div = document.getElementById("myDiv");

alert(div.getAttribute("id")); //"myDiv"

alert(div.getAttribute("class")); //"bd"

alert(div.getAttribute("title")); //"Body text"

alert(div.getAttribute("lang")); //"en"

alert(div.getAttribute("dir")); //"ltr"

注意,传递给 getAttribute()的特性名与实际的特性名相同。因此要想得到 class 特性值,应 该传入"class"而不是"className",后者只有在通过对象属性访问特性时才用。如果给定名称的特性不存在,getAttribute()返回 null。

通过 getAttribute()方法也可以取得自定义特性(即标准 HTML 语言中没有的特性)的值,以 下面的元素为例:

<div id="myDiv" my_special_attribute="hello!"></div>

这个元素包含一个名为 my_special_attribute 的自定义特性,它的值是"hello!"。可以像取

得其他特性一样取得这个值,如下所示:

var value = div.getAttribute("my_special_attribute");

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

任何元素的所有特性,也都可以通过 DOM 元素本身的属性来访问。当然,HTMLElement 也会有 5 个属性与相应的特性一一对应。不过,只有公认的(非自定义的)特性才会以属性的形式添加到 DOM 对象中。以下面的元素为例:

<div id="myDiv" align="left" my_special_attribute="hello!"></div>

因为 id 和 align 在 HTML 中是<div>的公认特性,因此该元素的 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()方法。

在 IE7及以前版本中,通过 getAttribute()方法访问 style 特性或 onclick 这样的事件处理特性时,返回的值与属性的值相同。换句话说,getAttribute("style")返回一个对象,而 getAttribute("onclick")返回一个函数。虽然 IE8 已经修复了这个bug,但不同IE版本间的不一致性,也是导致开发人员不使用getAttribute()访问HTML特性的一个原因。

3. 设置特性

与getAttribute()对应的方法是 setAttribute(),这个方法接受两个参数:要设置的特性名和 值。如果特性已经存在,setAttribute()会以指定的值替换现有的值;如果特性不存在,setAttribute() 则创建该属性并设置相应的值。来看下面的例子:

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

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

div.setAttribute("title", "Some other text");

div.setAttribute("lang","fr");

div.setAttribute("dir", "rtl");

通过 setAttribute()方法既可以操作 HTML 特性也可以操作自定义特性。通过这个方法设置的 特性名会被统一转换为小写形式,即"ID"最终会变成"id"。 因为所有特性都是属性,所以直接给属性赋值可以设置特性的值,如下所示。

div.id = "someOtherId";

div.align = "left";

不过,像下面这样为 DOM 元素添加一个自定义的属性,该属性不会自动成为元素的特性。

div.mycolor = "red";

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

这个例子添加了一个名为 mycolor 的属性并将它的值设置为"red"。在大多数浏览器中,这个属 性都不会自动变成元素的特性,因此想通过 getAttribute()取得同名特性的值,结果会返回 null。 可是,自定义属性在 IE 中会被当作元素的特性,反之亦然。

在 IE7 及以前版本中,setAttribute()存在一些异常行为。通过这个方法设置 class 和 style 特性,没有任何效果,而使用这个方法设置事件处理程序特性时也 一样。尽管到了 IE8 才解决这些问题,但我们还是推荐通过属性来设置特性。

要介绍的最后一个方法是 removeAttribute(),这个方法用于彻底删除元素的特性。调用这个方 法不仅会清除特性的值,而且也会从元素中完全删除特性,如下所示: div.removeAttribute("class"); 这个方法并不常用,但在序列化 DOM 元素时,可以通过它来确切地指定要包含哪些特性。

IE6 及以前版本不支持 removeAttribute()。

4. attributes 属性

Element 类型是使用 attributes 属性的唯一一个 DOM 节点类型。attributes 属性中包含一个 NamedNodeMap,与 NodeList 类似,也是一个“动态”的集合。元素的每一个特性都由一个 Attr 节点表示,每个节点都保存在 NamedNodeMap 对象中。NamedNodeMap 对象拥有下列方法。

 getNamedItem(name):返回 nodeName 属性等于 name 的节点;

 removeNamedItem(name):从列表中移除 nodeName 属性等于 name 的节点;

 setNamedItem(node):向列表中添加节点,以节点的 nodeName 属性为索引;

 item(pos):返回位于数字 pos 位置处的节点。

attributes 属性中包含一系列节点,每个节点的 nodeName 就是特性的名称,而节点的 nodeValue 就是特性的值。要取得元素的 id 特性,可以使用以下代码。

var id = element.attributes.getNamedItem("id").nodeValue;

以下是使用方括号语法通过特性名称访问节点的简写方式。

var id = element.attributes["id"].nodeValue;

也可以使用这种语法来设置特性的值,即先取得特性节点,然后再将其 nodeValue 设置为新值, 如下所示。

element.attributes["id"].nodeValue = "someOtherId";

调用 removeNamedItem()方法与在元素上调用 removeAttribute()方法的效果相同——直接删 除具有给定名称的特性。下面的例子展示了两个方法间唯一的区别,即 removeNamedItem()返回表示被删除特性的 Attr 节点。

var oldAttr = element.attributes.removeNamedItem("id");

最后,setNamedItem()是一个很不常用的方法,通过这个方法可以为元素添加一个新特性,为此需要为它传入一个特性节点,如下所示。

element.attributes.setNamedItem(newAttr);

一般来说,由于前面介绍的 attributes 的方法不够方便,因此开发人员更多的会使用

getAttribute()、removeAttribute()和 setAttribute()方法。不过,如果想要遍历元素的特性,attributes 属性倒是可以派上用场。在需要将 DOM 结构序列化为 XML 或 HTML 字符串时,多数都会涉及遍历元素特性。以下代码展示了如何迭代元素的每一个特 性,然后将它们构造成 name="value" name="value"这样的字符串格式。

function outputAttributes(element){

var pairs = new Array(),

attrName,

attrValue,

i,

len;

for (i=0, len=element.attributes.length; i < len; i++){

attrName = element.attributes[i].nodeName;

attrValue = element.attributes[i].nodeValue;

pairs.push(attrName + "="" + attrValue + """);

}

return pairs.join(" ");

}

这个函数使用了一个数组来保存名值对,最后再以空格为分隔符将它们拼接起来(这是序列化长字符串时的一种常用技巧)。通过 attributes.length 属性,for 循环会遍历每个特性,将特性的名称和值输出为字符串。关于以上代码的运行结果,以下是两点必要的说明。

 针对 attributes 对象中的特性,不同浏览器返回的顺序不同。这些特性在 XML 或 HTML 代码中出现的先后顺序,不一定与它们出现在 attributes 对象中的顺序一致。

 IE7 及更早的版本会返回 HTML 元素中所有可能的特性,包括没有指定的特性。换句话说,返回 100 多个特性的情况会很常见。 针对 IE7 及更早版本中存在的问题,可以对上面的函数加以改进,让它只返回指定的特性。每个特性节点都有一个名为 specified 的属性,这个属性的值如果为 true,则意味着要么是在 HTML 中指定了相应特性,要么是通过 setAttribute()方法设置了该特性。在 IE 中,所有未设置过的特性的该属性值都为 false,而在其他浏览器中根本不会为这类特性生成对应的特性节点(因此,在这些浏览器中,任何特性节点的specified 值始终为 true)。改进后的代码如下所示。

针对 IE7 及更早版本中存在的问题,可以对上面的函数加以改进,让它只返回指定的特性。每个特 性节点都有一个名为 specified 的属性,这个属性的值如果为 true,则意味着要么是在 HTML 中指 定了相应特性,要么是通过 setAttribute()方法设置了该特性。在 IE 中,所有未设置过的特性的该 属性值都为 false,而在其他浏览器中根本不会为这类特性生成对应的特性节点(因此,在这些浏览器 中,任何特性节点的 specified 值始终为 true)。改进后的代码如下所示。

function outputAttributes(element){

var pairs = new Array(),

attrName,

attrValue,

i,

len;

for (i=0, len=element.attributes.length; i < len; i++){

attrName = element.attributes[i].nodeName;

attrValue = element.attributes[i].nodeValue;

if (element.attributes[i].specified) {

pairs.push(attrName + "="" + attrValue + """);

}

}

return pairs.join(" ");

}

这个经过改进的函数可以确保即使在 IE7 及更早的版本中,也会只返回指定的特性。

5. 创建元素

使用 document.createElement()方法可以创建新元素。这个方法只接受一个参数,即要创建元 素的标签名。这个标签名在 HTML 文档中不区分大小写,而在 XML(包括 XHTML)文档中,则是区 分大小写的。例如,使用下面的代码可以创建一个<div>元素。

var div = document.createElement("div");

在使用 createElement()方法创建新元素的同时,也为新元素设置了 ownerDocuemnt 属性。此时,还可以操作元素的特性,为它添加更多子节点,以及执行其他操作。来看下面的例子。

div.id = "myNewDiv";

div.className = "box";

在新元素上设置这些特性只是给它们赋予了相应的信息。由于新元素尚未被添加到文档树中,因此 设置这些特性不会影响浏览器的显示。要把新元素添加到文档树,可以使用 appendChild()、insertBefore()或 replaceChild()方法。下面的代码会把新创建的元素添加到文档的<body>元素中。

document.body.appendChild(div);

一旦将元素添加到文档树中,浏览器就会立即呈现该元素。此后,对这个元素所作的任何修改都会实时反映在浏览器中。

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

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

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

 不能设置动态创建的<iframe>元素的 name 特性。

 不能通过表单的 reset()方法重设动态创建的<input>元素(第 13 章将讨论 reset()方法)。

 动态创建的 type 特性值为"reset"的<buttou>元素重设不了表单。

 动态创建的一批 name 相同的单选按钮彼此毫无关系。name 值相同的一组单选按钮本来应该用于表示同一选项的不同值,但动态创建的一批这种单选按钮之间却没有这种关系。 上述所有问题都可以通过在createElement()中指定完整的HTML标签来解决,如下面如下面的例子所示。

if (client.browser.ie && client.browser.ie <=7){

//创建一个带 name 特性的 iframe 元素

var iframe = document.createElement("<iframe name="myframe"></iframe>");

//创建 input 元素

var input = document.createElement("<input type="checkbox">");

//创建 button 元素

var button = document.createElement("<button type="reset"></button>");

//创建单选按钮

var radio1 = document.createElement("<input type="radio" name="choice" "+

"value="1">");

var radio2 = document.createElement("<input type="radio" name="choice" "+

"value="2">");

}

与使用 createElement()的惯常方式一样,这样的用法也会返回一个 DOM 元素的引用。可以将这个引用添加到文档中,也可以对其加以增强。但是,由于这样的用法要求使用浏览器检测,因此我们建议只在需要避开 IE 及更早版本中上述某个问题的情况下使用。其他浏览器都不支持这种用法。

6. 元素的子节点

元素可以有任意数目的子节点和后代节点,因为元素可以是其他元素的子节点。元素的 childNodes 属性中包含了它的所有子节点,这些子节点有可能是元素、文本节点、注释或处理指令。 不同浏览器在看待这些节点方面存在显著的不同,以下面的代码为例。

<ul id="myList">

<li>Item 1</li>

<li>Item 2</li>

<li>Item 3</li>

</ul>

如果是 IE 来解析这些代码,那么<ul>元素会有 3 个子节点,分别是 3 个<li>元素。但如果是在其 他浏览器中,<ul>元素都会有 7 个元素,包括 3 个<li>元素和 4 个文本节点(表示<li>元素之间的空 白符)。如果像下面这样将元素间的空白符删除,那么所有浏览器都会返回相同数目的子节点。

<ul id="myList"><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>

对于这段代码,<ul>元素在任何浏览器中都会包含 3 个子节点。如果需要通过 childNodes 属性 遍历子节点,那么一定不要忘记浏览器间的这一差别。这意味着在执行某项操作以前,通常都要先检查 一下 nodeTpye 属性,如下面的例子所示。

for (var i=0, len=element.childNodes.length; i < len; i++){

if (element.childNodes[i].nodeType == 1){

//执行某些操作

}

}

这个例子会循环遍历特定元素的每一个子节点,然后只在子节点的 nodeType 等于 1(表示是元素节点)的情况下,才会执行某些操作。

如果想通过某个特定的标签名取得子节点或后代节点该怎么办呢?实际上,元素也支持 getElementsByTagName()方法。在通过元素调用这个方法时,除了搜索起点是当前元素之外,其他 方面都跟通过 document 调用这个方法相同,因此结果只会返回当前元素的后代。例如,要想取得前面 <ul>元素中包含的所有<li>元素,可以使用下列代码。

var ul = document.getElementById("myList");

var items = ul.getElementsByTagName("li");

要注意的是,这里<ul>的后代中只包含直接子元素。不过,如果它包含更多层次的后代元素,那么各个层次中包含的<li>元素也都会返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值