学习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的更多相关文章

  1. 一篇文章搞懂高级程序员、架构师、技术总监、CTO从薪资到技能的区别

    一篇文章搞懂高级程序员.架构师.技术总监.CTO从薪资到技能的区别 http://youzhixueyuan.com/senior-programmers-architects-technical-d ...

  2. 一篇文章搞懂python2、3编码

    说在前边: 编码问题一直困扰着每一个程序员的编程之路,如果不将它彻底搞清楚,那么你的的这条路一定会走的格外艰辛,尤其是针对使用python的程序员来说,这一问题更加显著, 因为python有两个版本, ...

  3. 五分钟学Java:一篇文章搞懂spring和springMVC

    原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 什么是Spring,为什么你要学习spring? 你第一次接触spring框架是在什么时候?相信很多人和我一样,第一次了 ...

  4. 一篇文章搞懂filebeat(ELK)

    本文使用的filebeat是7.7.0的版本本文从如下几个方面说明: filebeat是什么,可以用来干嘛 filebeat的原理是怎样的,怎么构成的 filebeat应该怎么玩 一.filebeat ...

  5. 一篇文章搞懂Android组件化

    网上组件化的文章很多,我本人学习组建化的过程也借鉴了网上先辈们的文章.但大多数文章都从底层的细枝末节开始讲述,由下而上给人一种这门技术“博大精深”望而生畏的感觉.而我写这篇文章的初衷就是由上而下,希望 ...

  6. 一篇文章搞懂Linux安全!

    Linux是开放源代码的免费正版软件,同时也是因为较之微软的Windows NT网络操作系统而言,Linux系统具有更好的稳定性.效率性和安全性. 在Internet/Intranet的大量应用中,网 ...

  7. InfluxDB从原理到实战 - 一篇文章搞懂InfluxDB时区

    0x00 简介    InfluxDB默认以UTC时间存储并返回时间戳,当接收到一个时序数据记录时,InfluxDB将时间戳从本地时区时间转换为UTC时间并存储,查询时,InfluxDB返回的时间戳对 ...

  8. 一篇文章搞懂Python装饰器所有用法

    01. 装饰器语法糖 如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上 ...

  9. 一篇文章搞懂android存储目录结构

    前言 前两天因为开发一个app更新的功能,我将从服务器下载的apk文件放在了内部存储目录(测试手机为小米,路径为:data/user/0/packagename/files)下面,然后安装的时候一直安 ...

随机推荐

  1. DOM-访问元素

    id:元素在文档中唯一标识符. title:有关元素的附加说明信息,一般通过工具提示条显示出来. lang:元素内容的语言编码,很少使用 dir:语言方向,职位“Ltr”(从左至右).Rtl(从右至左 ...

  2. javascript中字符串常用操作总结

    String对象属性 (1) length属性 length算是字符串中非常常用的一个属性了,它的功能是获取字符串的长度.当然需要注意的是js中的中文每个汉字也只代表一个字符,这里可能跟其他语言有些不 ...

  3. ARC基本原理

    基本简介 ARC是Automatic Reference Counting(自动引用计数器)的简称. ARC是ios5.0引入的新特性,完全消除手动管理内存的繁琐,编译器会自动在适合的代码里面插入适当 ...

  4. 19、网络编程 (Socket套接字编程)

    网络模型 *A:网络模型 TCP/IP协议中的四层分别是应用层.传输层.网络层和链路层,每层分别负责不同的通信功能,接下来针对这四层进行详细地讲解. 链路层:链路层是用于定义物理传输通道,通常是对某些 ...

  5. 使用springcloud gateway搭建网关(分流,限流,熔断)

    Spring Cloud Gateway Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 ...

  6. Python Django Ajax 传递列表数据

    function getTableContent(node) { event.preventDefault(); var tr = node.parentNode.parentNode; var id ...

  7. 网络编程: 基于TCP协议的socket, 实现一对一, 一对多通信

    TCP协议  面向连接 可靠的 面向字节流形式的 tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端 TCP协议编码流程: 服务器端:                 客户端 实例化对 ...

  8. Python爬虫学习记录【内附代码、详细步骤】

    引言: 昨天在网易云课堂自学了<Python网络爬虫实战>,视频链接 老师讲的很清晰,跟着实践一遍就能掌握爬虫基础了,强烈推荐! 另外,在网上看到一位学友整理的课程记录,非常详细,可以优先 ...

  9. 直接拿去用!每个App都会用到的LoadingLayout

    前言 项目里都会遇到几种页面,分别为加载中.无网络.无数据.出错四种情况,经常要使用,所以封成库引用了,方便使用,顺便分享出来.先看一下效果: 原理比较简单,继承FrameLayout,在xml渲染完 ...

  10. git报错:Pull is not possible because you have unmerged files解决方法

    在git pull的过程中,如果有冲突,那么除了冲突的文件之外,其它的文件都会做为staged区的文件保存起来. 重现: $ git pull A    Applications/Commerce/B ...