DOM
DOM
基础概念
DOM
DOM(document object model)译为文档对象模型,JavaScript会将文档(HTML页面)看成一系列标签的集合,并提供了一系列的API来操作HTML文档,比如对标签进行增删查改操作,或者修改CSS,这样的的话借助JavaScript能够实现动态页面。
- DOM 0级:在96年之前ie浏览器和网景浏览器为了抢夺市场,分别实现了一套JavaScript用于操作HTML的API。因为是分别实现的,没有标准,在正式DOM标准出来之前,统称它们的相关API为DOM0级。
- DOM 1级:98年w3c出台了第一版DOM API的标准,基本IE8就使用了该标准。DOM1级只能简单的操作HTML标签,比如提供
document.images
来获取页面上所有的<img>
标签等。 - DOM 2级:目前所有浏览器都支持的版本。增强了对页面的控制,以及添加了对CSS的支持,以及事件的支持。IE9+
- DOM 3级:目前所有浏览器都支持的版本,将API进行模块化,更方便管理和更新。
DOM树
为了方便对HTML页面进行操作,JavaScript把HTML页面抽象成一个具有层次的文档结构,我们称为“DOM”,因为按照层级来进行描述有点类似倒挂的树。每个HTML标签都是一个节点,其中标签内部的属性和文本内容在JavaScript中也会作为一个节点存在。
<a href="http://www.baidu.com">百度一下</a>
- 该
<a>
标签在JavaScript中会作为一个节点,而<a>
内部的href
属性和文本百度一下
也会作为一个节点存在。
DOM节点
w3c规定了根据代码的不同作用将节点分成了12种类型,常用的只有3种:
元素节点-Element Node
:指的是HTML标签。属性节点-Attribute Node
:指元素节点中的一个属性。文本节点-TextNode
:指的是元素节点中的文本内容。
常用API:
nodeName
:节点的名称,比如<div>
的nodeName
是DIV
。nodeType
:指的是节点的类型,是一个数字:1
:该节点是一个元素节点,即HTML标签。2
:该节点是一个属性节点3
:该节点是一个文本节点
DOM基本操作
document对象
document对象是DOM的核心,大多数DOM API都有该对象提供。
DOM的一般使用流程
- 获取HTML标签
- 修改或获取HTML标签的内容
- 修改HTML标签的css
基础API
- 获取body标签
- 获取HTML标签
- 获取页面上的标题
- 获取页面上的地址
- 获取页面上的所有图片
- 获取页面上的所有表单
//获取<body>标签
var body = document.body;
//获取<html>标签
var html = document.documentElement;
//获取页面上的标题
var title =document.title;
//获取页面地址
var url = document.URL;
//获取页面上的所有图片,即<img>
var imgs = document.images;
//获取页面上的所有表单
var forms = document.forms;
HTML标签API
获取HTML元素
-
通过id:
var 标签变量名 = document.getElementById("标签的id属性值");
-
通过class:
var 标签数组变量名 = document.getElementsByClassName("class属性值");
获取的是一个数组,哪怕是没有数据,或者只有一个,也是返回的数组。
-
通过标签名:
var 标签数组变量名 = document.getElementsByTagName("标签名");
获取的是一个数组,哪怕是没有数据,或者只有一个,也是返回的数组。
-
通过CSS选择器来查找标签:
-
querySelector
:匹配第一个找到的HTML标签。var 标签变量名 = document.querySelector("标签的CSS选择器");
-
querySelectorAll
:匹配找到的所有标签.返回的是一个数组,通过下标获取具体的一个标签。var 标签变量名 = document.querySelectorAll("标签的CSS选择器");
-
-
获取兄弟标签
-
previousElementSibling
:获取上一个兄弟标签 -
nextElementSibling
:获取下一个兄弟标签var 标签数组变量名 = 标签变量名.previousElementSibling; //获取上一个兄弟标签 var 标签数组变量名 = 标签变量名.nextElementSibling; //获取下一个兄弟标签
-
-
获取父标签
-
parentElement
:获取父标签var 标签数组变量名 = 标签变量名.parentElement;
-
-
获取子标签
-
firstElementChild
:获取第一个子标签 -
lastElementChild
:获取最后一个子标签 -
children
:获取所有的直接子标签,返回一个数组。var 标签数组变量名 = 标签变量名.firstElementChild; var 标签数组变量名 = 标签变量名.lastElementChild; var 标签数组变量名 = 标签变量名.children;
-
获取/修改HTML元素的内容/属性
-
内容
-
value
属性// 1. 先获取HTML标签 var 标签变量名 = document.querySelector('input'); // 2. 获取HTML标签的内容 标签变量名.value; //修改 标签变量名.value = 新数据;
-
innerHTML
:获取标签内部的HTML代码。一般针对于<标签名> </标签名>
这种模式的标签。// 1. 先获取HTML标签 var 标签变量名 = document.querySelector('#box'); // 2. 获取HTML标签的内容 标签变量名.innerHTMl; //修改 标签变量名.innerHTML = 新数据;
-
innerText
:获取标签内的文本内容。一般针对于<标签名> </标签名>
这种模式的标签。// 1. 先获取HTML标签 var 标签变量名 = document.querySelector('#box p'); // 2. 获取HTML标签的内容 标签变量名.innerText; //修改 标签变量名.innerText = 新数据;
-
-
-
属性
-
获取
var 标签数组变量名 = 标签变量名.getAttribute("属性名");
-
设置
标签变量名.setAttribute("属性名", "属性值");
-
例子:
<img src="img/id1.jpg" id="img">
//获取 var img =document.querySelector("#img"); var src = img.getAttribute("src"); document.write(src); //输出img/id1.jpg //修改 img.setAttribute("src", "img/id2.jpg");
-
添加/删除HTML元素
-
添加
先利用
document.createElement()
生成一个新的标签,新建的标签是存在于代码中,页面上不会显示出来。再利用appendChild
或insertBefore
将第一步新建的标签追加到页面上。-
document.createElement
:新建标签var 标签变量名 = document.createElement("标签名"); //例子: var newDiv = document.createElement("div");
-
appendChild
:将某个标签追加到页面中,作为其父标签的最后一个子标签。父标签变量名.appendChild(新标签变量名); //例子: var father = document.querySelector('#mydiv'); father.appendChild(newDiv);
-
insertBefore
:将某个标签追加到页面上,并作为其父标签的子标签并放在指定兄弟标签之前。父标签变量名.insertBefore(新标签变量名,兄弟标签变量名); //例子: var father = document.querySelector('#box'); var brother = document.querySelector('#box p'); father.insertBefore(newP,brother);
-
-
删除
获取待删除的标签以及其父标签,父标签调用
removeChild
来删除子标签。-
removeChild()
:删除子标签父标签变量名.removeChild(待删除的子标签); //例子: var father = document.querySelector('#box'); var p = document.querySelector('#box p'); father.removeChild(p);
-
修改CSS
-
获取
-
getComputedStyle
:能够获取某个标签的所有最终使用样式。该函数会返回一个对象,需要我们定义变量接收后进行使用。该对象中包含了该标签的所有样式,可以通过对象变量名.css属性名
来获取某个css属性。var 变量名 = getComputedStyle(标签变量名, null);
-
-
设置
-
标签变量名.style.CSS属性名 = CSS属性值
:修改CSS属性值,JavaScript会将设置的CSS样式作为嵌入样式放在标签的style
属性中,这样可以保证CSS样式优先级最高。标签变量名.style.CSS属性名 = CSS属性值;
-
点击事件
-
当用户点击某个按钮的时候,执行指定的js代码。
-
在标签上写
onclick = "js代码"
,所有标签都可以添加:<div onclick = "js代码">点击我</div>
-
在js中写代码:
标签变量名.onclick = function(){ //当该标签被点击时要执行的代码 }
-
例如:
<button onclick="demo()">登录</button> <button id="reg-btn">注册</button>
//方法一 function demo(){ console.log('被点击了'); } //方法二 var button = document.querySelector('#reg-btn'); button.onclick = function(){ console.log('button被点击了'); }
-
-
可使用
this
指针获取被点击的标签-
在
onclick
中添加this
作为实参,在函数中用形参来接收 。<div onclick="函数名(this);"></div>
function 函数名(elem){ //elem就是被点击的标签本身 elem.innerText = "被点击了"; }
-
在js中指定
onclick
时,直接在function
中用this
来指代被点击的标签本身。<button id="demo">登录</button>
var btn = document.querySelector('button'); btn.onclick = function(){ this.innerText = "被点击了"; //直接使用this }
-
eval
JavaScript内置函数,可以把某个字符串作为JavaScript代码执行并返回执行的结果。
eval('var a=10; alert(a)');//弹框输出10
var num = eval("2+2");
document.write(num);//4
substr\substring
都是针对字符串的内置API,用于获取字符串中的一部分字符,即获取子字符串。
字符串.substr(子字符串的开始下标,子字符串的字符数量);
字符串.substring(子字符串的开始下标,子字符串的结束下标);
//获取hello
var str = "hello world";
var newStr = str.substr(0,5);
var newStr =str.substring(0,5);
document.write(newStr); //hello
- substring左闭右开,不包含结束下标。
- substr/substring如果直接到末尾,第二个实际参数可以省略不写。
DOM事件
事件基础
概念
事件是指用户跟页面进行交互的各种动作的统称,比如点击、双击、按压键盘、滚轮等。我们可以通过事件的处理实现当用户触发某个动作时能够去执行相应的js代码。
分类
UI
-
load
:在资源加载完成之后触发。只针对window
对象以及img
标签有效,对window
对象即页面加载完成之后触发,对img
标签即图片加载完成之后进行触发。 -
resize
:在页面的尺寸发生变化时进行触发。标签变量名.onload = function(){ //资源加载完成之后 } 标签变量名.onresize = function(){ //标签尺寸变化时进行触发 }
- 对于
window.onload
来说,可以保证里面的代码是在页面DOM树加载完之后执行,就避免了head
标签里的DOM代码失效的问题。 resize
一般是针对整个页面。
- 对于
鼠标
-
click
:单击事件。 -
dblclick
:双击事件。 -
mousemove
:当鼠标在指定标签内部移动时会触发。 -
mouseenter
:当鼠标进入指定标签内部会触发一次。 -
mouseleave
:当鼠标离开指定标签内部会触发一次。<div ondblclick="" onmousemove="" onmouseenter="" onmouseleave=""> </div>
标签变量名.ondblclick = function(){ //要执行的代码 } 标签变量名.onmousemove = function(){ //该标签内部移动时会执行 } 标签变量名.onmouseenter = function(){ //进入该标签内部时会执行 } 标签变量名.onmouseleave = function(){ //离开该标签内部时会执行 }
键盘
-
keydown
:按任意键触发。 -
keyup
:按任意键后完全释放触发。 -
keypress
:按任意键至底将释放时触发。<div onkeyup="" onkeydown="" onkeypres=""> </div>
标签变量名.onkeydown = function(){ //按任意键会执行 } 标签变量名.onkeypress = function(){ //按任意键后完全释放会执行 } 标签变量名.onkeyup = function(){ //按任意键至底将释放时触发会触发 }
- 这三个事件只有
keyup
可以获取输入框最新的数据,所以一般keyup用的最多。 - 一般用来实时监测用户的输入是否符合要求。
- 这三个事件只有
焦点
-
focus
:一般是表单元素获取焦点时触发,比如鼠标点击选中输入框。 -
blur
:一般是表单元素失去焦点时触发。<div onfocus="" onblur=""> </div>
标签变量名.onfocus = function(){ //获取焦点时会执行 } 标签变量名.onblur = function(){ //失去焦点时会执行 }
文本
-
change
:一般是下拉菜单中切换选项时触发。<select onchange="" > </select>
标签变量名.onchange = function(){ //下拉菜单中切换选项时会执行 }
- 一般用于根据菜单选项动态调节下一个菜单内容,比如省、市、县选择框。
滚轮
-
mousewheel
:当鼠标滚轮滚动时触发(FireFox不兼容)。 -
DOMMouseScroll
:当鼠标滚轮滚动时触发(FireFox可兼容)。<div onmousewheel = ""> </div>
标签变量名.onmousewheel = function(){ //鼠标滚轮滚动时会执行 } 标签变量名.addEventListener("DOMMouseScroll",function(){ //鼠标滚轮滚动时会执行 })
- 一般用于实现长列表数据动态加载(参考京东首页数据滚动加载)。
触摸屏
-
touchstart
:单个手指点击时触发。 -
touchend
:单个手指离开屏幕时触发。 -
touchmove
:单个手指在屏幕上移动时触发。标签变量名.addEventListener('touchstart',function(){ //单个手指点击时会执行 }) 标签变量名.addEventListener('touchend',function(){ //单个手指离开屏幕时会执行 }) 标签变量名.addEventListener('touchmove',function(){ //单个手指在屏幕上移动时会执行 })
事件流
概念
为了解决针对嵌套标签的事件触发位置问题(点儿算不算点爹),所以才有了事件流的概念。事件流
是指事件触发的顺序流向,即谁先触发事件,谁后触发,针对嵌套标签。根据事件触发的顺序不同事件流分为冒泡
和捕获
。
冒泡
从具体触发事件的子标签开始冒泡,会依次的去触发父标签及祖先标签的事件。
<div class="box-1">div-1
<div class="box-2">div-2
<div class="box-3">div-3
<div class="box-4">div-4
<div class="box-5">div-5</div>
</div>
</div>
</div>
</div>
<!--给5个div设置事件。对于冒泡来说,触发的事件顺序是box-5 ->box-4->box-3->box-2->box-1->body->html->document对象.由具体的子标签到父标签-->
捕获
从document开始触发事件,一直触发到具体的子标签。
<div class="box-1">div-1
<div class="box-2">div-2
<div class="box-3">div-3
<div class="box-4">div-4
<div class="box-5">div-5</div>
</div>
</div>
</div>
</div>
<!--给5个div设置事件。对于冒泡来说,触发的事件顺序是box-5 <-box-4<-box-3<-box-2<-box-1<-body<-html<-document对象.由document到body,到具体的子标签-->
事件执行阶段
概念
当用户触发某个事件时,该事件的完整的执行流程就是事件执行流程(阶段)。
流程
- 第一阶段:先执行一次捕获,即父标签触发(最顶层能够到document),一直到具体的子标签触发。
- 第二阶段:事件目标阶段,真正用户要执行事件的子标签进行触发。
- 第三阶段:执行一次冒泡,由具体的子标签到父标签依次触发。
注意点
- 事件目标阶段实际上是将第一阶段的末尾以及第三阶段的开头划分为了第二阶段。只是为了说明目前是对用户真正要执行的标签进行处理,实际第二阶段不会再单独的触发一次。
- 实际的事件处理中,只会在捕获或冒泡中二选一,用的最多的是冒泡。
事件处理程序
概念
当触发某个事件时要执行的程序(即代码),根据更新分为DOM0级和DOM2级。
DOM 0级
DOM 0 级只能是在事件执行阶段中的第三阶段处理。
-
标签变量名.on事件名 = function(){}
标签变量名.on事件名 = function(){ }
<div on事件名="要执行的代码"></div>
DOM 2级
-
.addEventListener()
-
.removeEventListener()
//添加事件处理程序 标签变量名.addEventListener('事件名', 事件触发要执行的函数, 是否是捕获阶段处理); //第三个参数是布尔型,true表示捕获阶段处理,false表示冒泡阶段处理,默认false。 //删除事件处理程序 标签变量名.removeEventListener('事件名', 事件触发要执行的函数, 是否是捕获阶段处理); //例子:body设置点击事件的处理程序为handler,捕获阶段处理 document.body.addEventListener('click', handler, true); //删除 document.body.removeEventListener('click', handler, true); function handler(){ console.log("body被点击了"); }
如果要删除的话,必须保证删除使用的3个参数和添加时写的3个参数完全一样,且第二个参数必须是一个函数名,而不是一个具体的function。
上述二者的区别
DOM2级可以选择在捕获阶段或冒泡阶段进行处理,而DOM0级只能在冒泡阶段处理。
兼容性
DOM2级只能IE9+支持,DOM0级全系支持。
event对象
概念
JavaScript为了能够在处理事件相关代码时,能够获取该事件的相关信息,JavaScript在触发某事件时会自动创建一个event对象并收集该事件的相关信息,该event对象会作为事件处理函数的实参,所以我们在写事件处理代码时需要定义形参接收。
接收event对象后,可以使用event对象里所包含的相关内容。比如事件的触发标签,事件类型名,甚至可以控制冒泡行为,获取触发事件时鼠标的所在位置。
获取event对象
每次触发事件时会新建event对象。
<div> <div>
var div = document.querySelector('div');
div.addEventListener('click', function(event){
//event参数就保存了该对象
console.log(event);
})
常用属性和API
-
target
:真正触发事件的具体的子标签。 -
currentTarget
:当前正在处理的事件标签,因冒泡或捕获,所以实际的标签会不同,不常用。 -
stopPropagation()
:取消进一步的冒泡。 -
preventDefault()
:取消事件的默认行为。比如a标签的默认行为是跳转,如果调用了该函数后,a标签就不在有跳转功能。表单里的按钮也是一样,调用了该函数后,按钮就不具有表单提交功能。 -
type
:事件的类型名。 -
clientX&clientY
:指触发事件时,鼠标在当前窗口中的下标,以屏幕左上角为原点。 -
pageX&pageY
:获取鼠标的坐标,以屏幕左上角为原点,跟clientX或 Y
的不同的是,pageX&pageY
是以整个HTML文档作为参考。event对象名.target event对象名.clientX event对象名.clientY event对象名.preventDefault() event对象名.stopPropagation()
事件委托
概念
在给多个标签设置事件处理程序时,相关代码会很繁琐,重复度很高,该问题可通过事件委托解决。
事件委托又称事件代理,指利用了事件执行阶段中的冒泡机制并配合event对象来达到精简代码量效果的编程技巧,它不仅可以减少事件处理程序的代码量,还可以管理事件处理代码。
语法
-
给需要设置点击事件的标签的父标签设置事件处理程序。
-
利用
event.target
来判断真正触发事件的具体子标签,然后针对该子标签执行相应代码。document.querySelector('.box1').addEventListener('click',function(e){ console.log(e.target); }) document.querySelector('.box2').addEventListener('click',function(e){ console.log(e.target); }) //事件委托 document.body.addEventListener('click',function(e){ //区分:class id nodeName var classname = e.target.getAttribute('class'); if(classname=='box1'){ //点击了box1 div //执行box1的点击事件代码 console.log('点击了box1'); }else if(classname=='box2'){ //点击了box1 div //执行box1的点击事件代码 console.log('点击了box2'); } });
扩展
控制音频
-
play()
:用于控制视/音频的播放。 -
pause()
:用于控制视/音频的暂。<audio src="圣诞.wav" id="music" controls></audio>
var music = document.querySelector("#music"); music.play();//播放 music.pause();//暂停
-
video
标签和audio
标签使用方式一样。
表单提交或重置
-
submit()
:用于表单提交。 -
reset()
:用于表单重置。<form action="success.html" id="loginForm"> 用户名: <input type="text" id="user"> 密码:<input type="text" id="pass"> <button id="login-btn">登录</button> </form>
var form = document.querySelector("#loginForm"); form.submit(); //提交: form.reset(); //重置
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了