DOM
定义
DOM(Document Object Model)定义了表示和修改文档所需的方法。DOM对象为宿主对象,由浏览器厂商定义,用来操作HTML和XML。也有人称DOM是HTML以及XML的标准编程接口。
几个实例
- 点击指定div区域,使其背景颜色改变
<body>
<div> </div>
<script type = "text/javascript">
var div = document.getElementsByTagName('div')[0];
div.style.width = '100px';
div.style.height = '100px';
div.style.background = 'lightblue';
//第一次点击时变粉色,第二次点击时变蓝色:
var count = 0;
div.onclick = function() {
count++;
if (count % 2 == 1) {
div.style.background = 'pink';
} else {
div.style.background = 'lightblue';
}
}
</script>
</body>
- 一个选项卡功能
<body>
<div class="wrapper">
<button class="active"> ① </button>
<button> ② </button>
<button> ③ </button>
<div class="content" style="display:block">星星</div>
<div class="content">月亮</div>
<div class="content">太阳</div>
</div>
<script type="text/javascript">
//一个选项卡功能
var btn = document.getElementsByTagName('button');
var div = document.getElementsByClassName('content');
for (var i = 0; i < btn.length; i++) {
(function (n) {
btn[n].onclick = function () {
for (var j = 0; j < btn.length; j++) {
btn[j].className = "";
div[j].style.display = "none";
}
this.className = "active";
div[n].style.display = "block";
}
}(i))
}
</script>
</body>
- 在页面上写一个动态的div区域
<body>
<script type = "text/javascript">
var div = document.createElement('div');
document.body.appendChild(div); //添加div
div.style.width = "100px"; //设置div样式
div.style.height = "100px";
div.style.backgroundColor = "pink";
div.style.position = "absolute";
div.style.left = "0";
div.style.top = "0";
//版本1:匀速横向运动
/* setInterval(function () { //定时器:每隔100ms执行一次这里的函数
div.style.left = parseInt(div.style.left) + 1 + "px"; //横向位置的变换
}, 100)
//版本2:加速运动
var speed = 1;
setInterval(function () { //定时器:每隔100ms执行一次这里的函数
speed += speed/7; //加速运动
div.style.left = parseInt(div.style.left) + speed + "px"; //横向位置的变换
div.style.top = parseInt(div.style.top) + speed + "px"; //纵向位置的变换
}, 100)
//版本3:加速运动,且在指定位置停下
var speed = 1;
var timer = setInterval(function () { //定时器:每隔100ms执行一次这里的函数
speed += speed/7; //加速运动
div.style.left = parseInt(div.style.left) + speed + "px";
div.style.top = parseInt(div.style.top) + speed + "px";
if(parseInt(div.style.top) > 200 && parseInt(div.style.left) > 200) {
clearInterval(timer);
}
}, 100)
*/
//版本4:使用键盘的“上下左右”键来操作div的移动
document.onkeydown = function(e) {
switch(e.which) {
case 37: //使div向左移动
div.style.left = parseInt(div.style.left) - 2 + "px";
break;
case 38: //使div向上移动
div.style.top = parseInt(div.style.top) - 2 + "px";
break;
case 39: //使div向右移动
div.style.left = parseInt(div.style.left) + 2 + "px";
break;
case 40: //使div向下移动
div.style.top = parseInt(div.style.top) + 2 + "px";
break;
}
}
</script>
</body>
选择指定标签的几种方法
document 代表整个文档/页面
1 直接选择
document.getElementsByTagName()
document.getElementById() //不常用。在真正开发时,能使用class就不适用id
document.getElementsByClassName() //不常用。因为具有局限性:IE8及以下的IE版本中不可使用
document.getElementsByName() //不常用。只有部分标签才有name属性, 如表单、img、iframe
<body>
<div>
<p class="demo"></p>
</div>
<p></p>
<script type = "text/javascript">
var p = document.getElementsByClassName('demo')[0];
//无论通过什么来选出一个标签,其返回结果都是一个类数组;
//如果类数组中只有一个元素,也必须通过“[0]”才能真正的选出这个标签,否则p表示的是一个类数组。
</script>
</body>
2 通过CSS选择器选出指定标签
document.querySelector() //(只选出一个指定标签)不常用。在IE7及以下的版本中没有
document.querySelectorAll() //(选出所有的符合条件的指定标签)不常用。在IE7及以下的版本中没有 //这两个方法并不常用,其致命缺点是:不具有实时性——通过这两个方法选出来的标签是“死的”,如果后面的代码更改了这些标签,那么通过这两个方法选出来的那些标签仍是不改变的。但如果使用上面的一组方法来选出指定标签,就是“实时性”的,可以随着之后的代码对标签的修改而更新。
<body>
<div>
<strong></strong>
</div>
<div>
<span>
<strong></strong>
</span>
</div>
<script type = "text/javascript">
var strong = document.querySelector('div > span strong.demo');
var strong = document.querySelectorAll('div > span strong.demo');
</script>
</body>
<body>
<div></div>
<div class="demo"></div>
<div></div>
<script type = "text/javascript">
var div1 = document.querySelectorAll('div');
var div2 = document.getElementsByTagName('div');
var demo = document.getElementsByClassName('demo')[0];
var newDiv = document.createElement('div');
document.body.appendChild(newDiv);
</script>
</body>
3 遍历节点树选出指定标签
parentNode //父节点(最顶端为document)
childNodes //所有孩子节点
firstChild //第一个子节点
lastChild //最后一个子节点
nextSibling //后一个兄弟节点
previousSibling //前一个兄弟节点
查看父节点、兄弟节点
<body>
<div id="only" class="demo">
<strong></strong>
<span></span>
<em></em>
</div>
<script type = "text/javascript">
var div = document.getElementsByTagName('div')[0];
var strong = document.getElementsByTagName('strong')[0];
</script>
</body>
查看所有孩子节点
节点类型:
- 元素节点Element —— 1
- 属性节点 —— 2
- 文本节点Text —— 3
- 注释节点Comment —— 8
- document —— 9
- DocumentFragment(文档碎片) —— 11
节点的一个方法:
- hasChildNodes()
节点的四个属性:
- nodeName: 返回节点名称
- nodeValue: 只有文本节点和注释节点有该属性,用来查看文本或注释的内容,可以对其进行修改
- nodeType: 查看节点的类型,返回结果为上面对应的数字
- attributes: 用来保存一个元素节点的所有属性,是一个类数组
【实现一个方法,用来得到某标签的所有孩子节点中的元素节点(不使用children属性):】
<body> <div> 123 <strong></strong> <span></span> <em></em> </div> <script type = "text/javascript"> var div = document.getElementsByTagName('div')[0]; function retElementChild(node) { var temp = { //定义一个类数组,用来保存返回的结果 length : 0, push : Array.prototype.push, splice : Array.prototype.splice }; var child = node.childNodes; var len = child.length; for(var i = 0; i < len; i++) { if(child[i].nodeType === 1) { temp.push(child[i]); } } return temp; } console.log(retElementChild(div)); </script> </body>
<body>
<div>
123
<strong></strong>
<span></span>
</div>
<script type = "text/javascript">
var div = document.getElementsByTagName('div')[0];
</script>
</body>
4 遍历元素节点树选出指定标签
parentElement //IE9以下不兼容
children
firstElementChild //IE9以下不兼容
lastElementChild //IE9以下不兼容
nextElementSibling //IE9以下不兼容
previousElementSibling //IE9以下不兼容
<body>
<div>
<strong></strong>
<span></span>
<em></em>
</div>
<script type = "text/javascript">
var div = document.getElementsByTagName('div')[0];
var strong = document.getElementsByTagName('strong')[0];
</script>
</body>
DOM继承树
DOM结构树代表了一系列继承关系,所以也叫做DOM继承树。
1. document代表整个文档:
- document的构造函数是HTMLDocument
2. Document可以理解成一个构造函数,其特殊之处在于不能new对象,因为这是系统留给自己使用的:
- Document的用处:Document由于是一个构造函数,所以存在原型Document.prototype。这里我们需要知道的是,Document.prototype实际上是作为document的原型。下面可以进行验证——在Document.prototype上添加属性str,则能够在document上进行访问:
3. HTMLDocument的原型是Document.prototype,即:
HTMLDocument.prototype = { __proto__: Document.prototype }
- document和Document之间的关系就是:document继承自HTMLDocument.prototype,而HTMLDocument.prototype又继承自Document.prototype。
继承关系展示:
4. Text:文本节点的方法直接继承自Text的原型;
Comment:注释节点的方法直接继承自Comment的原型。
5. head, body等标签直接继承自HTMLHeadElement.prototype, HTMLBodyElement.prototype等。<script type = "text/javascript"> HTMLElement.prototype.test = 'test'; HTMLBodyElement.prototype.str = 'abc'; var body = document.getElementsByTagName('body')[0];//得到body标签中的所有属性 var head = document.getElementsByTagName('head')[0];//得到head标签中的所有属性 </script>
看下面的输出结果,可以清楚的知道其中的继承关系:
由于继承关系的限定,有:
- getElementById方法定义在Document.prototype上,故Element节点不能调用该方法。
- getElementByName方法定义在HTMLDocument.prototype上,则非HTMLDocument元素(如XMLDocument、Element)不能调用该方法。
- getElementsByTagName方法定义在Document.prototype和Element.prototype上(也因此,getElementsByTagName方法最为常用)。
实例:如何快速锁定到div中的span标签?
<body> <div> <span></span> </div> <span></span> <script type = "text/javascript"> //方法1: 不推荐 var span1 = document.getElementsByTagName('span')[0]; //方法2: 推荐 【理论支撑:getElementsByTagName方法定义在了Element.prototype上】 var div = document.getElementsByTagName('div')[0]; //在文档范围内寻找第一个div标签 var span = div.getElementsByTagName('span')[0]; //在第一个div标签范围内寻找第一个span </script> </body>
- HTMLDocument.prototype定义了一些常用的属性,如body, head等,它们分别指代< body >,< head >标签。
- Document.prototype上定义了documentElement属性,指代文档的根元素< html >。
- getElementsByClassName、querySelector、querySelectorAll在Document.prototype和 Element.prototype上均有定义。
节点的增删改操作
1. 增
document.createElement() //增加元素节点
document.createTextNode() //增加文本节点
document.createComment() //增加注释节点
document.createDocumentFragment() //创建文档碎片节点
注意:使用上面的方法后,只是新增了节点,但还没有把这些节点真正的插入到页面上。还需要使用下面的方法:
PARENTNODE.appendChild(a)
/PARENTNODE.insertBefore(a, b)
(该方法的PARENTNODE必须是div元素,表示:在div中的b前插入a——insert a before b)
- 实例:
<body>
<div></div>
<script type = "text/javascript">
var div = document.getElementsByTagName('div')[0];
var text = document.createTextNode('Hello World!');
div.appendChild(text); //如果是想插入到页面上,即<body>标签上,则:document.body.appendChild()
var span = document.createElement('span');
div.appendChild(span);
var text1 = document.createTextNode('Hi ❤ ');
span.appendChild(text1);
span.appendChild(text);//该语句使得div.appendChild(text);失效。这说明appendChild()是"剪切"操作,而不是"复制"操作。
</script>
</body>
- appendChild()的"剪切"效果:
- insertBefore():
2. 删
PARENTNODE.removeChild() //被删除的元素作为该方法的返回值,如需要,可进行保存
CHILDNODE.remove() //被删除的元素被彻底删除,不返回出来。es5中新增
3. 改
PARENTNODE.replaceChild(new, origin); //new元素替换origin元素
<body>
<div>
<span></span>
</div>
<script type = "text/javascript">
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
var p = document.createElement('p');
</script>
</body>
元素节点的属性和方法
1. 元素节点的属性
innerHTML
innerText //火狐中也可使用textContent
<body>
<div>
<span></span>
</div>
<script type = "text/javascript">
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
var p = document.createElement('p');
</script>
</body>
1.1 innerHTML
- 查看或修改HTML结构。
1.2 innerText
- 查看或修改元素的文本内容。
- 注意,一旦对其进行修改,其内的所有结构也全部消失:
2. 元素节点的方法
ele.setAttribute(属性名, 属性值) //为ele元素设置属性
ele.getAttribute(属性名)
- 实例:
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
#only{
font-size:20px;
color:#fff;
background-color:pink;
}
</style>
</head>
<body>
<div>
<span>Hello!</span>
</div>
<script type = "text/javascript">
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
</script>
</body>
- 应用:为所有元素都设置‘this-name’属性,属性值为对应的标签名。
<body>
<div></div>
<span></span>
<strong></strong>
<script type = "text/javascript">
var all = document.getElementsByTagName('*');
for(var i = 0; i < all.length; i++) {
all[i].setAttribute('this-name', all[i].nodeName);
}
</script>
</body>
- 应用:使用上面的知识点写出下面的页面结构:
<div c="example">
<p class="slogan" >Hello World!</p>
</div>
<body>
<script type = "text/javascript">
var div = document.createElement('div');
var p = document.createElement('p');
div.setAttribute('c', 'example');
p.setAttribute('class', 'slogan');
p.innerText = 'Hello World!';
document.body.appendChild(div);
document.body.appendChild(p);
</script>
</body>