在DOM中搜索元素
大部分时间里,为了与用户进行交互,我们需要找到元素并进行修改。
虽然我们可以使用childNodes,children等方式,但他们只允许在相邻的元素中进行移动。
幸运的是,我们有其他的全局方法可以实现这一点。
方法
document.getElementById
获取元素的最快方式是使用其 id。
下例将使用 id='info' 从document中搜索div标签。不管它在什么地方,始终都能被找到。
<body>
<div id="info">Info</div>
<script>
var div = document.getElementById('info')
alert( div.innerHTML )
</script>
</body>
注意,同一个id只应该出现一起。当然,你也可以破坏这个规则,但这么做的话根据浏览器 getElementById 会出现不同的加过。因此最好还是坚持标准规范,保证指定的 id 只有一个元素。
如果没有找到元素,将会返回null。
隐式 id 变量
所有的浏览器都会隐式的为 id 创建一个变量。
举例说明,运行以下代码。它会输出 test。因为 a 是由IE生成的对元素的引用。
<div id="a">test</div> <script> alert(a) </script>
运行下段代码在IE中可能会导致错误,请看下面的例子。
<div id="a">test</div> <script> a = 5 // (x) alert(a) </script>
如果你从IE运行,它将不会工作。x行有错误的,因为:
- a 是对DIV的引用(没问题)
- IE生成的引用不能被重写。
但是你可以使用var a来代替a:
<div id="a">test</div> <script> var a = 5 alert(a) // all fine </script>
IE教了我们其他的好的实验。
我们都知道window是全局对象。JavaScript在最后会在window中搜索所有的东西。
那么window.window是什么,window === window.window 是否成立
逻辑上来看,它是相同的,但... 。
除了IE的大部分浏览器中,window.window只是对引用的一个钩子,window也是。因此 window === window.window,成立。
并且 window.window.window 也是跟 window.window 一样。
但是在IE,顶层的 window 是特殊的对象拥有着特殊的功能,然而 window.window 有点像标准的window对象。
你可以在IE中验证以下代码:
alert(window === window.window) // false alert(window.window === window.window.window) // true为什么说它是重要的。
当你使用一个变量不适用 var 时,它会有一些功能及Bug,因为IE使用它自己的外部window对象对它进行处理。
其中最明显的有:
1. 对元素的id重新进行赋值 - IE会报错:
<div id="a">...</div> <script> a = 5 // error in IE! Ok if "var a = 5" alert(a) // will never happen </script>2. 从外部window变量中对它进行递归遍历 - 下面的代码会在 IE<9 中死掉。
<script> // recurse is explicitly defined on the outer window window.recurse = function(times) { if (times !== 0) recurse(times-1) } recurse(13) </script>该BUG在IE9中已修复。
document/node.getElementsByTagName
通过这个方法可以使用特定的标签名进行检索,结果为array-like的元素集合。
// get all div elements
var elements = document.getElementsByTagName('div')
下例会展示出如何从 document 中检索出 INPUT 标签集合,并对它们进行遍历:
<table id="myTable">
<tr>
<td>Your age:</td>
<td>
<label>
<input type="radio" name="age" value="young" checked/> under 18
</label>
<label>
<input type="radio" name="age" value="mature"/> from 18 to 50
</label>
<label>
<input type="radio" name="age" value="senior"/> older than 60
</label>
</td>
</tr>
</table>
<script>
var elements = document.getElementsByTagName('input')
for(var i=0; i<elements.length; i++) {
var input = elements[i]
alert(input.value+': '+input.checked)
}
</script>
我们也可以直接访问第一个元素:
var element = document.getElementsByTagName('input')[0]
可以通过使用 '*' 而不是标签来获取所有的元素:
// get all elements in the document
document.getElementsByTagName('*')
Limit search by parent element
getElementsByTagName可以被 document 调用,它也可以被普通的DOM元素进行调用。
下例演示 getElementsByTagName 如何在普通的DOM元素中进行调用的。
<ol id="people">
<li>John</li>
<li>Rodger</li>
<li>Hugo</li>
</ol>
<script>
var elem = document.getElementById('people')
var list = elem.getElementsByTagName('li')
alert(list[0].innerHTML)
</script>
在elem中通过使用elem.getElementsByTagName('li')查找所有的 LI。点号之前的被称为上下文对象。
document.getElementsByName
元素是支持 name attribute的,可以通过name来查询它们。
上面的例子我们还可以使用以下代码:
var elements = document.getElementsByName('age')
document/node.getElementsByClassName
这个方法在除了IE<9以外的所有的浏览器所支持。
它根据 class 名称进行搜索,不是attribute。尤其是,它支持多个类。
下面的例子将演示它如何根据 class名 查找对应元素。
请不要使用 IE<9 浏览器:
<div class="a b c">Yep</div>
<script>
alert( document.getElementsByClassName('a')[0].innerHTML )
</script>
跟 getElementsByTagName 一样它也可以从普通的DOM元素进行查找。
document/node.querySelector, querySelectorAll
querySelector 和 querySelectorAll可以根据 CSS3 语法检索元素。
querySelector 只返回第一个元素(深度优先),querySelectorAll 返回全部。
它们运行在除了IE<8以外的所有的浏览器里。下面列表为IE支持的情况:
- IE8必须在IE8末世,而不是适配末世。
- IE中它不支持CSS3,只支持到CSS2.1,因此没有CSS3那么强大,但大部分情况都够用了。
下面的代码会查询到最后的元素为 LI 并且父节点为 UL 的所有匹配元素。他们都可以再IE8里运行。
<ul>
<li>The</li>
<li>Test</li>
</ul>
<ul>
<li>Is</li>
<li>Passed</li>
</ul>
<script>
var elements = document.querySelectorAll('UL > LI:last-child')
for(var i=0; i<elements.length; i++) {
alert(elements[i].innerHTML )
}
</script>
querySelector 是 querySelectorAll('...')[0] 的缩写。
现代浏览器中使用XPath
现代浏览器都支持强力的XPath搜索,XPath在XML世界中是一个通用的DOM检索工具。大部分也可以在HTML中使用该工具。
下面的例子将会使用XPath语法检索出所有包含XPath的 H3 元素。
var result = document.evaluate("//h3[contains(text(),'XPath')]", document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
for (var i=0; i<result.snapshotLength; i++) {
alert(result.snapshotItem(i).innerHTML)
}
唯一的里外是IE(包含9),它支持XML文档。文档可以使用 XMLHTTPRequest(AJAX) 技术从服务器进行加载,但如果要在文档中进行搜索,你需要显示的把该网页载入到XML文档对象。
在现实生活中 querySelector 可以更加方便的解决任务,但多了解不同的实现方式始终是有好处的。
查询结果是实时的(活动的)
所有的DOM搜索,都会匹配多个元素,会返回一个 array-like集合,通过它有获取长度和下标功能。它也可以像数组一样使用 for 进行遍历。
但是下标和长度属性是它和数组仅有的共同点,并且返回的元素集合有一个特殊的类型 NodeList 或 HTMLCollection。
因此它没有 push,pop 或JavaScript Array对象的其他属性。
相反,通过 getElementsBy* 方法查询后的结果集是活着的。你可以选择元素并更改文档 - 之前查询后的结果也会自动进行更新。
下例将会说明当元素被移除后结果集的长度是如何被更改的。
<div id="outer">
<div id="inner">Info</div>
</div>
<script>
var outerDiv = document.getElementById('outer')
var divs = document.getElementsByTagName('div')
alert(divs.length)
outerDiv.innerHTML = '' // clear inner div
alert(divs.length)
</script>
这个特性只存在于集合中。如果你得到一个元素的引用,则该引用不会成为 null。例如,元素 elem = document.getElementById('inner') 当外部 div 被清除后它也会一直存在。
但是 querySelectorAll 有些特殊。因为性能原因,它会返回 非活跃 的 NodeList。它是通用规则的一个例外。
实践
考虑以下的HTML:
<!DOCTYPE HTML>
<html>
<body>
<label>The table</label>
<form name="age-form">
<table id="age-table">
<tr>
<td id="age-header">Your age:</td>
<td>
<label>
<input type="radio" name="age" value="young"/> under 18
</label>
<label>
<input type="radio" name="age" value="mature"/> 18 to 50
</label>
<label>
<input type="radio" name="age" value="senior"/> after 60
</label>
</td>
</tr>
</table>
</form>
</body>
下面为根据上面的DOM结构的一些练习。
查找表格中的所有的 laben 元素。结果是 label 类型的数组。
编写一个函数
checkInsideTable(id),当传一个id,并且该id的元素在id为age-table的表格中存在的话返回true。如果没有此元素,则返回false:
例如:
checkInsideTable('age-header') // true
checkInsideTable('top') // false
checkInsideTable('non-existant-id') // false
标签链接
<style>
.external { background-color: yellow }
</style>
<ul>
<li><a href="http://google.com">http://google.com</a></li>
<li><a href="/tutorial">/tutorial.html</a></li>
<li>
<a href="ftp://ftp.com/file.zip">ftp://ftp.com/file.zip</a>
</li>
<li><a href="http://nodejs.org">http://nodejs.org</a></li>
</ul>
给所有的外部链接添加 external 类。
显示子节点数量
编写程序,当 li 节点拥有者 li 子节点的时候给该 li 节点方括号及子li节点的数量。
如果没有li子节点则不进行任何操作。
下面代码为html代码:
<ul>
<li>About Animals
<ul>
<li>Mammal
<ul>
<li>Cows</li>
<li>Donkeys</li>
<li>Dogs</li>
<li>Tigers</li>
</ul>
</li>
<li>Others
<ul>
<li>Snakes</li>
<li>Birds</li>
<li>Lizards</li>
</ul>
</li>
</ul>
</li>
<li>
About Fish
<ul>
<li>
About aquarium fishes
<ul>
<li>Guppy</li>
<li>Scalare</li>
</ul>
</li>
<li>
Sea fish
<ul>
<li>Sea trout</li>
</ul>
</li>
</ul>
</li>
</ul>
希望的输出结果是
- About Animals [9]
- Mammals [4]
- Cows
- Donkeys
- Dogs
- Tigers
- Others [3]
- Snakes
- Birds
- Lizards
- Mammals [4]
- About Fish [5]
- About aquarium fishes [2]
- Guppy
- Scalare
- Sea fish [1]
- Sea trout
- About aquarium fishes [2]
更多
在任意一个html文档中执行以下代码
var aList1 = document.getElementsByTagName('a');
var aList2 = document.querySelectorAll('a');
document.body.appendChild(document.createElement('a'));
alert(aList1.length - aList2.length);
会输出什么,为什么?
总结
有5种方式查询DOM:
getElementByIdgetElementsByTagNamegetElementsByNamegetElementsByClassName(除了 IE<9)querySelector(除了 IE<8 和 IE8 兼容模式)
上面的所有的方法都可以搜索节点内的其他元素。除了最后一个之外的所有方法都是 活动的 集合。
大部分浏览器支持XPath,但现在很少被使用。
在DOM中搜索元素的更多相关文章
- angularjs中展示富文本编辑器文本,向DOM中插入元素
前几天在用textangular富文本编辑器插件时,将存储的文本及格式存储到数据库中,但是从后台接口中再向angular页面插入时却不能执行,即在Angular中操作DOM没有实现,后来查看了一下,操 ...
- JS 清除DOM 中空白元素节点
HTML中的空白节点会影响整体的HTML的版面排榜 例如: 制作百度首页时,两个input之间的空白节点将本来是要整合在一起的搜索栏硬是把按钮和搜索框分离出现好丑的间隙 这时我们就可以用js清除这个空 ...
- DOM中获取元素的节点兼容IE6-8封装,带jquery源码分析children
<ul id="box"> <li>第一个节点</li> <li>第二个节点</li> <li>第三个节点& ...
- javascript判断元素存在和判断元素存在于实时的dom中的方法
今天(周六)下午我在公司加班时不知道要干什么,就打开公司的一个wordpress项目网站,想看下之前自己做的一个网页是否有问题. 打开网站首页,我习惯性的打开了chrome的调试工具,然后鼠标开始滚动 ...
- DOM中元素节点、属性节点、文本节点的理解
DOM中元素节点.属性节点.文本节点的理解 节点信息 每个节点都拥有包含着关于节点某些信息的属性.这些属性是:nodeName(节点名称) nodeValue(节点值) nodeType(节点类型) ...
- js中迭代元素特性与DOM中的DocumentFragment类型 笔记
JS中迭代元素特性 在需要将DOM结构序列化为XML或者HTML字符串时,多数都会涉及遍历元素的特性,这个时候attributes属性就可以派上用场. 以下代码展示了如何迭代元素的每一个特性,然后将他 ...
- detach([expr]) 从DOM中删除所有匹配的元素。
detach([expr]) 概述 从DOM中删除所有匹配的元素.大理石构件 这个方法不会把匹配的元素从jQuery对象中删除,因而可以在将来再使用这些匹配的元素.与remove()不同的是,所有绑定 ...
- DOM中操作结点的属性_操作元素结点的样式
有俩种方式操作结点的属性. 首先我们需要先获取所要操作的结点元素: var uname=document.getElementById("uname"); var gan=unam ...
- jQuery中兄弟元素、子元素和父元素的获取
我们这里主要总结jQuery中对某元素的兄弟元素.子元素和父元素的获取,原声的Javascript代码对这些元素的获取比较麻烦一些,而jQuery正好对这些方法进行封装,让我们更加方便的对这些元素进行 ...
随机推荐
- bzoj1720: [Usaco2006 Jan]Corral the Cows 奶牛围栏
金组题什么的都要绕个弯才能AC..不想银组套模板= = 题目大意:给n个点,求最小边长使得此正方形内的点数不少于c个 首先一看题就知道要二分边长len 本来打算用二维前缀和来判断,显然时间会爆,而且坐 ...
- 害死人不偿命的(3n+1)猜想
卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反复砍下去,最后一定在某一步得到n=1.卡拉兹在1950年的世界数 ...
- 安卓中級教程(3):ScrollView
以上是scrollview的圖例,可見srollview是一種滑動功能的控件,亦是非常常見的控件. 一般寫法如下: package com.mycompany.viewscroller; import ...
- MySQL数据的主从复制、半同步复制和主主复制详解
一.MySQL复制概述 ⑴.MySQL数据的复制的基本介绍 目前MySQL数据库已经占去数据库市场上很大的份额,其一是由于MySQL数据的开源性和高性能,当然还有重要的一条就是免费~不过不知道还能免费 ...
- TotalCommander 之 配置
一.设置配置界面: 1.进入设置界面 点击菜单栏的配置,然后再点击配置里面的选项,便会出现Total Commander设置的界面. 2.设置字体 刚开始,大家会发现这不是我们熟悉的字体啊 ...
- python学习道路(day10note)(线程,进程)
1.计算机的发展史 看alex的博客吧,了解一下可以了 2.线程与GIL简介 #线程 #一道单一的指令的控制流,寄生在进程中 #单一进程里的多个线程是共享数据的 #多个线程涉及修改共享数据的时候需要枷 ...
- IO口
STM32的每个IO端口都有7个寄存器来控制.他们是:CRH CRL IDR ODR BSRR BRR LCKR.我们常用的IO端口寄存器位CRL CRH IDR ODR.CRL CRH控制着每个IO ...
- [转]你不需要jQuery
完全没有否定jQuery的意思,jQuery是一个神奇的.非常有用的工具,可以节省我们大量的时间. 但是,有些时候,我们只需要jQuery的一个小功能,来完成一个小任务,完全没有必要加载整个jQuer ...
- Altium Designer 生成Gerber文件
- 在asp.net WebForms中使用路由Route
1.新建WebForms应用程序 2.打开Global.asax文件代码如下: public class Global : System.Web.HttpApplication { protected ...