一篇文章搞懂DOM

学习JavaScript肯定是会遇到DOM操作,那么什么是DOM?它又是干嘛用的?这篇文章为你揭晓答案。

DOMdocument object model的缩写,简称文档对象模型。

简单的说DOM是一套对文档的内容进行抽象和概念化的方法。我们可以把HTML文档模型化,当作对象来处理。

基本概念:

文档(document): HTMLXML文件。

节点(node):HTML文档中的所有内容都可以称之为节点,常见的节点有 元素节点 属性节点 文本节点 注释节点

元素(element): HTML文档中的标签可以称为元素

我们可以把一个HTML文档看做一个树形结构的对象,每一个标签会形成一个分支,这样就很容易理解了,如下图所示(图片来自w3school)。

 

知道了什么是DOM,肯定要问DOM有什么用?

DOMHTML文档抽象成一个对象,肯定是为了方便使用JavaScriptHTML文档进行操作。DOM的作用就是为了对页面的结构内容进行操作,增加页面的动态特性。

好了,知道了DOM是干嘛用的,那么下面我们就学习如何进行DOM操作。

DOM操作主要分四个部分:

1、获取HTML节点及修改节点的属性

2、修改节点的样式

3、给节点绑定事件

4、节点操作

现在我们进行一一介绍

获取HTML节点与修改节点属性(包含表单元素)

DOM提供了三个获取节点的方法

方法一:

getElementById()   //根据id属性获取一个DOM对象,区分大小写,符合代码规范

通过id寻找一个元素(找到的是一个元素对象) 该方法只能被document对象调用(同一个文档中id不能重复)

<div id="box"></div>

var box = document.getElementById(“box”);

方法二:

getElementsByTagName()    //根据标签返回多个DOM对象

通过标签名寻找一类元素(找到的是由元素对象组成的伪数组) 即可以被document调用,又可以被元素对象调用,被元素对象调用时表示在该元素对象内部执行查找

通常针对多个标签,而且常会要用到for循环。

<div class="cl" id=“cl”>

    <div class="cl2"></div>

    <div class="cl2"></div>

</div>

<div class="cl"></div>

<div class="cl"></div>


var divs = document.getElementsByTagName("div");// 获取页面上所有div,divs是一个伪数组

var cl = document.getElementById("cl");// 获取id为cl的元素

var cl2s = cl.getElementsByTagName("div");// 获取cl元素下面所有的div标签,cl2s是一个伪数组

方法三:

getElementsByClassName()

通过类名寻找一类元素

<div class="cl" id=“cl”>

    <p class="cl"></div>

    <span class="cl"></div>

</div>

<a class="cl"></a>

var cls = document.getElementsByClassName("cl");//获取到的是一个伪数组,里面装的是div p span a这四个元素对象

获得到了节点元素后我们就可以对节点元素的属性进行修改了。

DOM也提供了两个方法供我们获取和修改元素的属性值。

getAttribute()

getAttribute是一个函数,用于获取节点属性。它只有一个参数,即所需要查询的属性的名字。getAttribute不属于document对象,所有不能通过document对象调用,只能通过元素节点对象调用。

<div id="box" title=hello></div>
var box = document.getElementById(“box”); console.log(box.getAttribute(“title”));

通过这个方法我们可以获取元素boxtitle属性值为hello

setAttribute()

setAttribute也是一个函数,用于修改节点属性。与getAttribute用法类似,不同的地方在于它有两个参数,第一个为属性名,第二个参数为设定的属性值。

<div id="box" title=hello></div>


var box = document.getElementById(“box”);

console.log(box.setAttribute(“title”,”world”));

此时,box节点的title属性值已经变为world

是不是感觉so easy.

其实还有更为简便的方法来修改属性值,直接使用点语法就可以了。

获取属性值

var 变量=box.title;

修改属性值

box.属性名 = “属性值

是不是感觉更简单呢。

在此我只举例了title属性,当然元素的属性还有很多,比如img标签的src属性,我们可以更改src属性来切换图片。还可以设置表单元素的属性

type可以设置input元素的类型

value可以设置input元素的值

checked可以设置input元素是否选中

selected 可以设置下拉列表select中的option是否被选中

disabled 可以设置input元素是否被禁用

好了,属性的操作就到此为止。

获取节点与控制样式

关于节点的获取,上面只用到了三个方法,但是实际的项目HTML文档往往是很复杂的,

文档中所有的节点之间都存在这样或那样的关系。节点间的各种关系可以用传统的家族关系来描述,相当于把文档树比喻成家谱。在 HTML 中,可以将<body>元素看成是<html>元素的子元素;相应地,也就可以将<html>元素看成是<body>元素的父元素。而<head>元素,则可以看成是<body>元素的同胞元素,因为它们都是同一个父元素<html>的直接子元素。

首先我们来认识一下文档的层级结构,都有那些关系。

childNodes //子节点

children //子元素 虽然不是早期DOM标准中的方法,但是所有浏览器都支持

nextSibling //下一个兄弟节点

nextElementSibling //下一个兄弟元素 有兼容性问题

previousSibling//上一个兄弟节点

previousElementSibling //上一个兄弟元素 有兼容性问题

firstChild //第一个节点

firstElementChild //第一个子元素 有兼容性问题

lastChild //最后一个子节点

lastElementChild //最后一个子元素 有兼容性问题

parentNode //父节点 (一定是元素节点,所以无需处理)

所有获取节点相关属性都没有兼容性问题

注意:节点和元素不是同一个概念,文章开头说过,在此提醒一下。

获取子节点&子元素

  • childNodes: 获取指定元素的子节点,包括文本节点、元素节点等
  • children: 获取知道元素的子元素,只会获取元素节点。<ul id="list">
    <li><a href="javascript:void(0)">首页</a></li>

    <li><a href="javascript:void(0)">播客</a></li>

    <li><a href="javascript:void(0)">博客</a></li>

    <li><a href="javascript:void(0)">相册</a></li>

    <li><a href="javascript:void(0)">关于</a></li>

    <li><a href="javascript:void(0)">帮助</a></li>

</ul>
<script> var ul = document.getElementById("list"); var lis = ul.getElementsByTagName("li"); //不关心层级 只找指定标签 //缺点: 如果内部还有li 也会找到 var nodes = ul.childNodes; //子节点 只找子级 //缺点: 除了我们想要的元素节点 还会获取到其他节点 var children = ul.children;//子元素

</script>

childNodesDOM标准中规定的方法 获取节点的方式所有浏览器都支持
children不是DOM标准中规定的方法 因为很常用所有浏览器也都支持

在实际应用中,基本都是用children。

获取下一个兄弟节点

nextSibling:下一个兄弟节点

<input type="text" id="txtName">

<span></span>

<input type="text" id="txtPwd"><span></span>

<input type="button" id="btn" value="注册">

 <script>

var txt = document.getElementById("txtName");

var next = txt.nextSibling;// 获取到的是换行,空文本节点

var pwd = document.getElementById("txtPwd");

var next = pwd.nextSibling;// 获取到的是span元素,因为两个标签间没有其他节点

 </script>

获取下一个兄弟元素

nextElementSibling: 下一个兄弟元素

<input type="text" id="txtName">

<span></span>

 <script>

var txt = document.getElementById("txtName");

var next = txt.nextElementSibling;// 可以获取到span元素,只获取下一个兄弟元素,忽略非元素类型的节点

 </script>

获取父节点

parentNode: 获取元素的父节点,父节点肯定是一个元素

<div id = "box">
    <img src="1.jpg" id="img"/>
</div>
<script>
var img = document.getElementById("img");
var parent = img.parentNode; //获取到的就是id为box的div元素
 </script>

节点的获取我就先介绍到这里,关于兼容性的问题我会再做补充。

下面看一下如何进行节点的样式操作。

获取样式

  • 通过style只能获取行内样式
  • 获取的样式如果有单位,获取到的样式中也会带单位,类型是一个字符串

设置样式

1通过style设置样式

  • 通过style设置的是行内样式
  • 如果样式需要单位,设置时也需要把单位带上
div{

    100px;

    height:100px;

}

<div id="box"></div>

var box = document.getElementById("box");

consloe.log(box.style.width);// 打印的是空字符串,因为只能获取行内样式

box.style.width = "300px";// 设置的是行内样式,而且这里必须带单位

console.log(box.style.width);// 打印的是“300px“/

2通过类名设置样式

.b{

    100px;

    height:100px;

    background-color:red;

}

<div id="box"></div>

var box = document.getElementById("box");

// 通过类名设置样式 两种方式

box.className = "b";

box.setAttribute("class","b");

下面介绍事件绑定

绑定事件

事件三要素: 事件源 事件 事件处理程序

事件源.事件 = function(){

    // 事件处理程序

}

<img src="pic.jpg" id="img"/>

var img = document.getElementById("img");

img.onclick = function(){

   ...

}

img是事件源 事件是点击onclick 事件处理程序是函数体中的内容

下面为常用事件总结

属性

描述

Onblur

元素失去焦点。

Onchange

域的内容被改变。

Onclick

当用户点击某个对象时调用的事件句柄。

ondblclick

当用户双击某个对象时调用的事件句柄。

Onfocus

元素获得焦点。

onkeydown

某个键盘按键被按下。

onkeypress

某个键盘按键被按下并松开。

Onkeyup

某个键盘按键被松开。

Onload

一张页面或一幅图像完成加载。

onmousedown

鼠标按钮被按下。

onmousemove

鼠标被移动。

onmouseout

鼠标从某元素移开。

onmouseover

鼠标移到某元素之上。

onmouseup

鼠标按键被松开。

Onreset

重置按钮被点击。

Onresize

窗口或框架被重新调整大小。

Onunload

用户退出页面。

 

节点操作

节点操作就5种形式,克隆节点、添加节点、插入节点、移除节点和创建节点。

克隆节点 - cloneNode()

element.cloneNode(): 复制element节点

参数:布尔值,

true代表深层克隆,把当前节点和内部所有节点都复制一份

false代表浅层克隆,只复制当前节点

<div id="father">

    <div id="son"><div/>

</div>

var father = document.getElementById("father");

var son = document.getElementById("son");

var clone = son.cloneNode(true);// 把son这个div复制一份 复制出来的clone和son没有任何关系了

添加节点 - appendChild()

father.appendChild(son):son节点追加到father内部的最后位置

<div id="father">
    <div id="son"><div/>
</div>
<div id="demo"></div>

var father = document.getElementById("father");
var demo = document.getElementById("demo");
var clone = demo.cloneNode(true);// 将demo克隆一份

father.appendChild(clone);// 将克隆出来的clone追加到father中

// 此时页面结构应该为

<div id="father">

    <div id="son"><div/>

    <div id="demo"></div>

</div>

<div id="demo"></div>

//追加克隆节点对原节点不会产生影响

//如果代码如下 则会将demo节点直接移动到father节点下

father.appendChild(demo);// demo是页面上存在的节点

// 此时页面结构应该为

<div id="father">

    <div id="son"><div/>

    <div id="demo"></div>

</div>

插入节点 - insertBefore()

father.inserBefore(son1,son2): son1插入到father节点下的son2前面

<div id="father">

    <div id="son"><div/>

</div>

<div id="demo"></div>

var father = document.getElementById("father");

var son = document.getElementById("son");

var demo = document.getElementById("demo");

father.inserBefore(son,demo);//会直接将demo节点移动到father下的son前面       

插入克隆出来的节点也不会对原节点产生影响

 

移除节点 - removeChild()

father.removeChild(son): father下的son节点移除

<div id="father">

    <div id="son"><div/>

</div>

var father = document.getElementById("father");

var son = document.getElementById("son");

father.removeChild(son);// 直接将son节点删除

创建节点

document.write()

特点:只能被document调用,而且会覆盖页面上原有内容

document.write("<a href="http://www.baidu.com">百度</a>")

// 可以在页面上创建一个a标签,而且会覆盖页面上原有的所有内容

innerHtml()

特点:往页面添加html标签,可以限定范围

<div id="box"></div>

var box = document.getElementById("box");

box.innerHtml = "<a href="http://www.baidu.com">百度</a>";

// 追加后的结构为

<div id="box">

    <a href="http://www.baidu.com">百度</a>

</div>

createElement()

特点:动态创建标签,添加到页面需要配合appendChild使用。

<div id="box"></div>

var box = document.getElementById("box");
var input = document.createElement("input");

input.type = "text";
box.appendChild(input);

DOM的基本操作就到此为止了,如果对你有所帮助就给本文点个赞吧O(∩_∩)O

原文地址:https://www.cnblogs.com/thinkguo/p/7494830.html