一篇文章搞懂DOM
学习JavaScript肯定是会遇到DOM操作,那么什么是DOM?它又是干嘛用的?这篇文章为你揭晓答案。
DOM是document object model的缩写,简称文档对象模型。
简单的说DOM是一套对文档的内容进行抽象和概念化的方法。我们可以把HTML文档模型化,当作对象来处理。
基本概念:
文档(document): HTML或XML文件。
节点(node):HTML文档中的所有内容都可以称之为节点,常见的节点有 元素节点 属性节点 文本节点 注释节点。
元素(element): HTML文档中的标签可以称为元素。
我们可以把一个HTML文档看做一个树形结构的对象,每一个标签会形成一个分支,这样就很容易理解了,如下图所示(图片来自w3school)。
知道了什么是DOM,肯定要问DOM有什么用?
DOM把HTML文档抽象成一个对象,肯定是为了方便使用JavaScript对HTML文档进行操作。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”));
通过这个方法我们可以获取元素box的title属性值为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>
childNodes是DOM标准中规定的方法 获取节点的方式所有浏览器都支持
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{ width: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{ width: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
一篇文章搞懂DOM的更多相关文章
- 一篇文章搞懂高级程序员、架构师、技术总监、CTO从薪资到技能的区别
一篇文章搞懂高级程序员.架构师.技术总监.CTO从薪资到技能的区别 http://youzhixueyuan.com/senior-programmers-architects-technical-d ...
- 一篇文章搞懂python2、3编码
说在前边: 编码问题一直困扰着每一个程序员的编程之路,如果不将它彻底搞清楚,那么你的的这条路一定会走的格外艰辛,尤其是针对使用python的程序员来说,这一问题更加显著, 因为python有两个版本, ...
- 五分钟学Java:一篇文章搞懂spring和springMVC
原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 什么是Spring,为什么你要学习spring? 你第一次接触spring框架是在什么时候?相信很多人和我一样,第一次了 ...
- 一篇文章搞懂filebeat(ELK)
本文使用的filebeat是7.7.0的版本本文从如下几个方面说明: filebeat是什么,可以用来干嘛 filebeat的原理是怎样的,怎么构成的 filebeat应该怎么玩 一.filebeat ...
- 一篇文章搞懂Android组件化
网上组件化的文章很多,我本人学习组建化的过程也借鉴了网上先辈们的文章.但大多数文章都从底层的细枝末节开始讲述,由下而上给人一种这门技术“博大精深”望而生畏的感觉.而我写这篇文章的初衷就是由上而下,希望 ...
- 一篇文章搞懂Linux安全!
Linux是开放源代码的免费正版软件,同时也是因为较之微软的Windows NT网络操作系统而言,Linux系统具有更好的稳定性.效率性和安全性. 在Internet/Intranet的大量应用中,网 ...
- InfluxDB从原理到实战 - 一篇文章搞懂InfluxDB时区
0x00 简介 InfluxDB默认以UTC时间存储并返回时间戳,当接收到一个时序数据记录时,InfluxDB将时间戳从本地时区时间转换为UTC时间并存储,查询时,InfluxDB返回的时间戳对 ...
- 一篇文章搞懂Python装饰器所有用法
01. 装饰器语法糖 如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上 ...
- 一篇文章搞懂android存储目录结构
前言 前两天因为开发一个app更新的功能,我将从服务器下载的apk文件放在了内部存储目录(测试手机为小米,路径为:data/user/0/packagename/files)下面,然后安装的时候一直安 ...
随机推荐
- hadoop学习笔记(十一):MapReduce数据类型
一.序列化 1 hadoop自定义了数据类型,在hadoop中,所有的key/value类型必须实现Writable接口.有两个方法,一个是write,一个是readFileds.分别用于读(反序列化 ...
- bind9配置转发服务
修改bind主配置文件 $ vi /etc/named.conf//// named.conf//// Provided by Red Hat bind package to configure th ...
- SqlServer知识点
在公司天天写Sql写,存储过程,但是公司工具模板把创建的语句都写好了,只负责写里面的逻辑,久而久之,创建语句都不会写了.还有一些知识点都很模糊,平常使用的时候都不清楚,稀里糊涂的就在用.在这里整理一下 ...
- java基础之基础语法详录
[前言] java的语法先从基础语法学,Java语言是由类和对象组成的,其对象和类又是由方法和变量组成,而方法,又包含了语句和表达式. 对象:(几乎)一切都是对象,比如:一只熊猫,他的外观,颜色,他在 ...
- 关于Comparator和Comparable的理解
我们都知道,实现Comparator和Comparable这两个接口,可以实现对对象比较大小.那这个两个又有什么区别呢? comparator 1.接口类在java.util包里面,实现接口时需要导入 ...
- Mac下 KGDB连接Linux
kgdb按照资料说可以使用网络(kgdboe)和串口连接(kgdboc)等方式连接. 这里使用后者,资料比较多,下面是自己在Mac上进行配置连接的过程. 先说一下环境: 主机:Mac OSX 10.1 ...
- gotop(返回顶部)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 使用IntelliJ IDEA配置Erlang开发环境
这篇文章比较详细,感谢作者,拷贝过来做个记录 ————————————————————————————————————————————————————————————————————————————— ...
- 让input光标一直在最右边
有时候,我们需要使的input输入框的在点击时光标一直居右边 例如:移动端,用手指去点击输入框,在输入框较小,手指又比较大,那么经常会在点击后,光标会在已有文字时,居左 我们的输入框文字肯定要居中的需 ...
- mac系统使用介绍
点击左上角苹果-->关于本机 Dock-->偏好设置 推荐按装mac系统:OS X V10.8(山狮) Finder-->应用程序(安装程序)<==>我的电脑 Safar ...