文章目录
- JavaScript DOM笔记
- 1、DOM:文档对象模型
- 2、Document类型
- 2.1、获取元素
- 3、改变HTML
- 4、DOM事件
- 5、EventListener事件监听器
- 6、通过DOM向文档中添加、移除或替换HTML元素(节点)
- 7、HTMLCollection (只能包含HTML元素节点)
- 8、NodeList (可以包含各种类型的节点)
- 9、DOM操作CSS
- 10、event - 事件对象
- 11、事件类型
- 11.2、焦点事件
- 11.3、鼠标事件
JavaScript DOM笔记
记录一下DOM的笔记,不间断更新,详红宝书第14-16章
1、DOM:文档对象模型
如果把js代码写在上面,那么建议把js代码放在window.onload = function(){}里,确保代码执行时,页面中整个DOM对象已经加载完毕,否则无法获取到DOM对象
但是最好把js代码写在最下面(紧挨着</body>),使页面先加载出来,再执行代码,保证性能
· 文档:整个HTML网页文档
· 对象: 网页中每一个部分
· 模型:使用模型来表示对象之间的关系,方便获取对象
1.1、 Node类型
详见红宝书P402
· 节点Node:构成HTML文档最基本的单元
· 四类常用节点
-文档节点:整个HTML文档,其nodeValue为null -
-元素节点:HTML文档中的所有标签都是元素节点,使用element表示,其nodeValue为null
-属性节点:元素的属性,其nodeValue为属性值
-文本节点:HTML标签中文本的类容,其nodeValue为文本的内容
DOM把以上内容都看作是对象
举个例子
<p class="words">Hello World</p>
//整段代码是元素节点
//class="words" 这一部分是属性节点
//Hello World 是文本节点
JavaScript中所有节点类型都继承Node类型,因此所有节点都共享相同的基本属性和方法,每个节点都有nodeType属性,表示该节点的类型,节点类型由定义在Node类型上的12个数值常量表示。
1.1.1、nodeName与nodeValue
对元素而言,nodeName始终等于元素的标签名,而nodeType始终为null
2、Document类型
详见红宝书P407
事件:用户和浏览器之间的交互行为
HTML事件汇总
2.1、获取元素
获取元素后才能通过JavaScript对元素进行操作-
2.1.1、根据ID名获取
const/let a = document.getElementById('id名');
//id名为区分大小写的字符串
//返回值为一个元素节点对象
2.1.2、根据标签名获取
//两种方法
const/let a = document.getElementsByTagName('标签名');
const/let a = element.getElementsByTagName('标签名');
//返回值一组元素对象的集合(伪数组,数组元素是元素对象)
因为得到的是一个对象的集合,并且索引从0开始,所以要处理里面单个对象就要遍历
2.1.3、H5新增
1、根据类名获取
const/let a = document.getElementsByClassName('类名');
//返回值是一个满足条件元素对象的伪数组,使用时需要通过下标获取标签
const/let a = document.getElementsByClassName('box');
2、const/let a = document.querySelector('选择器');
这里注意选择器必须要加符号,比如类选择器,那么就必须加上“.”,eg.
const/let a = document.querySelector('.box');
//返回值:页面中第一个满足的HTML标签
3、const/let a = document.querySelectorAll('选择器');
//返回一组满足条件的元素
同样,选择器也要加上符号
const/let a = document.querySelectorAll('#box');
//返回值:以一个伪数组形式返回一个nodeList(节点列表)
getElementsByClassName 和 querySelectorAll 的区别(先留个坑,后面整理好了再更)
2.1.4、获取特殊元素(body、html)
获取body元素:document.body
获取html元素:document.documentElement
3、改变HTML
修改HTML最简单的方法是使用 innerHTML 属性
3.1、修改HTML元素的内容
语法: document.getElementById(“p1”).innerHTML=“新文本!”;
忽略格式,只是举个例子,下同
<html>
<p id="p1">Hello World</p>
<ul id="ul">
<li>1</li>
</ul>
</html>
<script>
document.getElementById('p1').innerHTML = "嗨!";//修改<p>的文本内容
document.getElementById('ul').innerHTML += "<li>2</li>";//增加一个<li>
</script>
3.2、修改HTML属性
语法:document.getElementById(id).attribute=新属性值
举个例子:
<html>
<img id="item" src="./图库/素材库/Dante/jackpot.jpg" alt="鬼泣展示图">
</html>
<script>
document.getElementById('item').innerHTML.src = "./图库/素材库/N vs DV.jpg";
//通过修改src来替换原来的图片
</script>
3.3、修改HTML样式
语法:document.getElementById(id).style.property=新样式
举个例子:
<html>
<p id="p1" style="color: red;">Hello World</p>
</html>
<script>
document.getElementById('p1').style.color="blue";
</script>
4、DOM事件
常用事件后续更新
完整版事件见此
4.1、事件属性
使用事件属性向html元素分配事件,eg.
<button onclick="displayDate()">点击显示日期</button>
4.2、使用DOM分配事件,当事件触发时,执行设置的函数
DOM允许用户使用JavaScript向HTML元素分配事件,语法如下
使用 对象.事件 = 函数 的方式 只能为一个对象绑定一个响应函数,多的会覆盖前面的
<html>
<button id="btn" onclick="displayDate()">点击显示日期</button>
</html>
<script>
//写法1:一次性使用时可以用这种写法
document.getElementById('btn').onclick=function(){
displayDate();
};
//点击id名为btn的button时,执行函数displayDate();
//写法2:需要多处使用时最好用这种写法
const/let btn = document.getElementById('btn');
btn.onclick=function(){
displayDate();
};
</script>
5、EventListener事件监听器
通过 addEventListener()方法 为指定对象添加事件句柄,不会覆盖已存在的句柄
语法:element.addEventListener(event, function, useCapture);
//注意在addEvenListener()方法中,不要使用on前缀
//比如应该使用click,而不是onclick
//useCapture为ture时,事件使用捕获传递。为false(默认)时,使用冒泡传递
1、可以通过 addEventListener() 为元素添加一个事件句柄,eg.
element.addEventListener('click',function(){
console.log('Hello World')
});
2、可以通过 addEventListener() 为他同一元素添加多个相同事件,相互之间为叠加关系,eg.
element.addEventListener('click',function_1);
element.addEventListener('click',function_2);
3、也可以通过 addEventListener() 为同一元素添加多个事件,eg.
element.addEventListener('click',function_1);//点击元素触发函数
element.addEventListener('mouseover',function_2);//鼠标悬停触发函数
element.addEventListener('mouseout',function_3);//鼠标移开触发函数
5.1、事件的冒泡传递与捕获传递
事件传递有两种方式:冒泡和捕获,这两种方式代表元素事件触发的不同顺序
以下面这段代码为例
<html>
<div id="div_1">
<p id="p_1">点击我</p>
</div>
</html>
<style>
#div_1{
position: relative;
width: 100px;
height: 50px;
background-color: rgb(239, 135, 95);
text-align: center;
}
#p_1{
position: absolute;
left: 25%;
top: 25%;
display: block;
margin: 0;
background-color: rgb(162, 162, 211);
}
</style>
效果图:
1.useCapture设置为true时,事件为捕获传递,即先触发最外部元素的事件,再由外到内依次触发内部元素的事件即:捕获传递:先外后内
<script>
const box_1 = document.getElementById("div_1");
const text = document.getElementById("p_1");
box_1.addEventListener('click',function() {
alert("我是捕获传递,你触发了box_1的点击事件");
}, true);//这里useCapture设置为true,为捕获传递
text.addEventListener('click',function() {
alert('我是捕获传递,你触发了text的点击事件');
}, true);
</script>
点击<p>的内容,先触发<div>的点击事件
点击确定后,会发现才触发<p>的点击事件
而如果点击<div>内非<p>的区域,那么只触发<div>的点击事件
按下确定后发现不会触发<p>的点击事件
2、useCapture设置为false时,事件为冒泡传递,即先触发最内部元素的事件,再由内到外依次触发外部元素的事件即:冒泡传递:先内后外
<script>
const box_1 = document.getElementById("div_1");
const text = document.getElementById("p_1");
box_1.addEventListener('click',function() {
alert("我是捕获传递,你触发了box_1的点击事件");
}, false);//这里useCapture设置为true,为捕获传递
text.addEventListener('click',function() {
alert('我是捕获传递,你触发了text的点击事件');
}, false);
</script>
点击<p>的内容,先触发<p>的点击事件
点击确定后,会发现才触发<div>的点击事件
而如果点击<div>内非<p>的区域,那么只触发<div>的事件
5.2、removeEventListener()
使用removeEventListener() 方法可以移除 addEventListener() 方法添加的事件句柄
语法:element.removeEventListener("event", function);
6、通过DOM向文档中添加、移除或替换HTML元素(节点)
6.1、添加 - appendChild() 与 insertBefore()
createElement():创建HTML元素
const box = document.createElement("div");
const para = document.createElement("p");
//创建了一个</div>元素
createTextNode():创建一个新的文本节点
const textNode = document.createTextNode("新的文本");
appendChild() 与 insertBefore()
1、appendChild() 方法用于将新元素添加到尾部
para.appendChild(textNode);
box.appendChild(para);
//如果html文件中的<div>内有2个<p>,那么用appendChild()新加入的para会放在第二个<p>之后
2、insertBefore() 方法用于将新元素添加到头部
para.insertBefore(textNode);
box.insertBefore(para);
//如果html文件中的<div>内有2个<p>,那么用appendChild()新加入的para会放在第一个<p>之前
6.2、移除 - removeChild()
如果想移除元素a,那么还需要找到它的父元素b
<html>
<div id="box">
<a id="link_1"></a>
<a id="link_2"></a>
</div>
</html>
使用 removeChild() 方法删除父元素中某个子元素
语法:父元素句柄.removeChild(待删除子元素句柄)
//以删除div内id为“link_2”的子元素为例
<script>
const parent = document.getElementById("box");
const child = document.getElementById("link_2");
parent.removeChild(child);
</script>
6.3、替换 - replaceChild()
语法:父元素句柄.replaceChild(替换元素句柄,被替换子元素的句柄);
7、HTMLCollection (只能包含HTML元素节点)
可以类比数组,通过索引去获取集合中的元素,但集合无法使用数组的方法
使用以下方法获取的是一个集合
1、getElementById(); //通过ID选取元素
2、getElementsByClassName(); //通过类名选取元素
3、getElementsByTagName(); //通过标签选取元素
4、getElementsByName(); //通过NAME属性选取元素
可以通过在方法后面添加索引号,来获取集合的指定元素,eg.
document.getElementsByClassName('pic1')[0];
7.1、集合对象的length属性
length属性获取的是集合中元素的数量
document.getElementsByClassName('pic1').length;
注意:如果要对获取到的集合中所有元素进行操作,那么应当使用遍历的方法
8、NodeList (可以包含各种类型的节点)
NodeList可以使用 length属性、forEach() 方法遍历,但它不是数组,数组特有的方法它不能使用
通过以下方法可以得到NodeList实例
Node.childNodes、document.querySelectorAll()
将NodeList转换为数组的方法:
Array.prototype.slice.call(NodeList名)
8.1、NodeList.prototype.item()
item()接受一个整数值作为索引号,返回该索引号位置上的成员,eg.
document.ul.childNodes.items(5);//返回第6个成员
但我们一般使用索引号直接取出成员,eg.
document.ul.childNodes[5];
HTMLCollection 与 NodeList 的区别
1、HTMLCollection 元素可以通过 name,id 或索引来获取。
2、NodeList 只能通过索引来获取。
3、只有 NodeList 对象有包含属性节点和文本节点。
9、DOM操作CSS
9.1、获取元素当前样式与相关属性
· 元素.currentStyle.样式名:只有IE浏览器支持,但IE已成为历史
· getComputedStyle()
getComputedStyle();//返回一个封装了当前元素对应样式的对象
需要传递两个参数,第一个是需要获取样式的元素,第二个是伪元素,一般传null
可以通过返回的对象对元素中的样式进行操作或者读取,eg.
getComputedStyle(div1,null).width;
注意:如果获取到的样式没有用css设置,那么会获取到实际的值而不是元素默认值
getStyle();//传两个参数,第一个是元素类名或者id名等,第二个是样式名的字符串
返回获取样式的值
eg.let c = getStyle(div1, "color");
修改样式的方法
举例:
document.querySelector('.words').style.color = 'red';//注意是字符型
· 获取元素可见宽高的数值:
-包括内边距:clientWidth、clientHeight
-包括内边距和边框:offsetWidth、offsetHeight
· 获取当前元素的定位父元素:offsetParent
-获取的是距离当前元素最近的设置了定位的祖先元素,若所有都没有设置定位,则返回则返回body
· 获取当前元素相对于其定位元素(offsetParent)的偏移量
-offsetLeft:水平偏移量
-offsetTop:垂直偏移量
· 获取滚动条滚动的距离
-scrollLeft:获取水平滚动的距离
-scrollTop:获取垂直滚动的距离
滚动到底的判断:
-垂直滚动到底:clientHeight == scrollHeight - scrollTop
-水平滚动到底:clientWidth == scrollLeft - scrollWidth
9.2、disabled 属性
用于设置一个元素是否被禁用,true为禁用,false为不禁用,改属性默认为false
10、event - 事件对象
事件传播的三个阶段:
1、捕获阶段
-该阶段从最外层的祖先元素,向目标元素进行事件的捕获,但默认此时不会触发事件
2、目标阶段
-事件捕获到目标元素,捕获结束开始在目标元素上触发事件
3、冒泡阶段
-事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件
· event对象只在事件处理程序执行期间存在,一旦执行完毕,就会被销毁
· 在事件对象event中封装了当期事件相关的一切信息,当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数。
所有浏览器都支持event对象。
使用event对象的一些方式
1、 btn.onclick = function(event){
console.log(event.type);//ty0pe可以是"click"、"mouseup"……
}
2、 btn.addEventListener("click" ,(event) => {
console.log(event.type);
}, false);
红宝书里还有用HTML实现相同效果的例子:
<input type = "button" value = "点我" onclick = "console.log(event.type)">
10.1、preventDefault() - 取消事件默认行为
preventDefault() 方法可以阻止特定事件的默认行为,比如阻止 <a>标签被点击时默认向href指定的url跳转
let myLink = document.getElementById("link_1");
myLink.onclick = function(event){
event.preventDefault();
};
任何可以通过 preventDefault() 方法取消默认行为的事件,其event对象的cancelable属性都会设置为true
所以应当先检测再使用该方法
10.2、stopPropagation() - 阻断事件流在DOM的传播
对event使用该方法后,会立即终止事件流在DOM的传播,取消后续事件捕获或者冒泡,不再执行该方法之后event的行为。
10.3、eventPhase属性 -
用于确定事件流所处阶段:
·捕获阶段 —>返回1
·在目标上被调用 —>返回2
·在冒泡阶段被调用 —>返回3
11、事件类型
11.1、用户界面事件 - 涉及与BOM交互的通用浏览器事件
11.1.1、load
加载项加载完成后触发
11.1.2、unload
在window上页面完全卸载后触发,在窗套上当所有窗格都卸载完成后触发、在上当相对应对象卸载完成后触发
11.1.3、absort
在元素上当相应对象加载完成前被用户提前终止下载时触发
11.1.4、error
当window加载JavaScript报错,、、窗套内容有加载失败时触发
11.1.5、选择
在文本框(或文段)上当用户选择了一个或多个字符时触发
11.1.6、调整大小
当窗口或窗格被缩放时触发
11.1.7、滚动
当用户滚动包含滚动条的元素时在元素上触发
11.2、焦点事件
11.2.1、blur(通用版:focusout)
当元素失去焦点时触发,这个事件不冒泡,该事件所有浏览器都支持
DOMFocusOut 在DOM3中被废除
11.2.2、focusin(focus冒泡版)
当元素获得焦点时触发,该事件冒泡
DOMFocusIn 在DOM3 Events中被废除
11.3、鼠标事件
DOM3 Events 规定了9种鼠标事件,对应类型为MouseEvent
事件 | 说明 |
---|---|
click | 鼠标左键单击 |
dblclick | 鼠标左键双击 |
mousedown (DOM3标准化 ) | 按下任意鼠标键 |
mouseenter (DOM3新增) | 鼠标光标从元素外移到元素内,该事件不冒泡 |
mouseleave(DOM3新增) | 鼠标光标从元素内移到元素外,该事件不冒泡 |
mousemove | 鼠标光标在元素上移动时反复触发 |
mouseout | 鼠标光标从一个元素移动到另一个元素时触发 |
mouseover | 鼠标光标从元素外移动到元素内 |
mouseup | 用户释放鼠标按键时触发 |
对 mousedown 和 mouseup 事件而言,event对象上有一个 button 属性,表示按下或释放的是哪个键
button = 0 ---> 按下或释放鼠标左键
button = 1 ---> 按下或释放鼠标滑轮
button = 2 ---> 按下或释放鼠标右键
客户端坐标获取: event.clientX、event.clientY
页面坐标获取: event.pageX、event.pageY
屏幕坐标获取: event.screenX、event.screenY
鼠标事件的公共属性:bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、ctrlKey 、 metaKey。
11.3.1、mousewheel - 鼠标滑轮事件
包括滑轮在垂直方向上的任意滚动,其event对象包含了鼠标事件的所有标准信息,此外还有一个名为 wheelDelta 的属性,其值的正负反应了滑轮滚动方向,数值反应了滚动幅度。
11.4、修饰键 - Shift、Ctrl、Alt、Meta
DOM规定了四个属性表示这四个修饰键的状态:
shiftKey、ctrlKey、altKey、metaKey
被按下时,对应状态布尔值为true、没有被按下时为false
11.5、键盘与输入事件
事件 | 说明 |
---|---|
keydown | 按下某个键时触发,持续按会重复触发 |
textInput(keypress在DOM3被废弃) | 按下键盘上某个键并产生字符时触发,持续按会重复触发 |
keyup | 用户释放键盘上某个键时触发 |
event属性 | 说明 |
---|---|
keyCode | 返回按下键的Unicode编码 |
key | 返回按下的键名字符 |
1、textInput是唯一的输入事件,textInput 会在文本被插入到文本框之前触发
2、如果一直按着某个键,那么某个键就会一直触发keydown和keypress(非字符键不触发),直到该键被释放才触发keyup
11.6、HTML5事件
11.6.1、contextmenu事件
Windows上点击鼠标右键 或者 Mac上 Ctrl+单击左键 时出现自定义上下文菜单
通常,自定义的上下文菜单都是通过 oncontextmenu 事件处理程序触发显示,并通过 onclick 事件处理程序触发隐藏。
11.6.2、beforeunload 事件
1、这个事件会在页面即将从浏览器中卸载时触发,如果页面需要继续使用,则可以不被卸载
2、这个事件会向用户显示一个确认框,其中的消息表明浏览器即将卸载页面,并请用户确认是希望关闭页面,还是继续留在页面上
该事件弹出的确认框中的文字由在 event.returnValue 中设置的字符串决定
11.6.3、 DOMContentLoaded 事件
window的load事件是在页面完全加载后触发,会花费较长时间,而DOMContentLoaded事件是在DOM树构建完成后立即触发,而不必等图片、js文件、css文件或其他资源加载完成。从而实现用户与页面更快地进行交互。
11.6.4、 readystatechange 事件
该事件旨在提供文档或元素加载状态的信息,通过readyState属性获取(该属性为支持 readystatechange事件的对象有)
readyState的可能字符串值 | 说明 |
---|---|
uninitialized | 对象存在并尚未初始化 |
loading | 对象正在加载数据 |
loaded | 对象已经加载完数据 |
interactive | 对象可以交互,但尚未加载完成 |
complete | 对象加载完成 |
11.6.5、pageshow 与 pagehide 事件(红宝书P526 - 527)
往返缓存:
该功能由Firefox 和 Opera开发,旨在使用浏览器“前进”和“后退”按钮时加快页面之间的切换。这个缓存不仅存储页面数据,也存储 DOM 和JavaScript 状态,实际上是把整个页面都保存在内存里。
pageshow 与 pagehide事件就是把往返缓存的行为暴露出来
11.6.6、hashchange 事件
用于在url散列值(即url中 # 之后的部分)发生变化时通知开发者
此事件的event对象中有两个属性:oldURL:保存变化前的url。newURL:保存变化后的url
window.addEventListener("hashchange", (event) => {
console.log(`Old URL: ${event.oldURL}, New URL: ${event.newURL}`);
});
使用location对象可以获取当期url散列值
语法:location.hash
11.7、设备事件(红宝书P528 - 531)
11.7.1、orientationchange 事件
11.7.2、deviceorientation 事件
11.7.3、devicemotion 事件
11.8、触摸及手势事件
11.8.1、触摸事件
事件 | 说明 |
---|---|
touchstart | 手指放到屏幕上时触发 |
touchmove | 手指在屏幕上滑动时连续触发。在这个事件中调用 preventDefault()可以阻止 |
滚动 | |
touchend | 手指从屏幕上移开时触发 |
touchcancel | 系统停止跟踪触摸时触发。文档中并未明确什么情况下停止跟踪 |
每个触摸事件的 event 对象都提供了鼠标事件的公共属性
触点的独特属性:
属性 | 说明 |
---|---|
touches | Touch 对象的数组,表示当前屏幕上的每个触点 |
targetTouches | Touch 对象的数组,表示特定于事件目标的触点 |
changedTouches | Touch 对象的数组,表示自上次用户动作之后变化的触点 |
每个Touch对象包含以下属性
属性 | 说明 |
---|---|
clientX | 触点在视口中的 x 坐标 |
clientY | 触点在视口中的 y 坐标 |
identifier | 触点在视口中的 y 坐标 |
pageX | 触点在页面上的 x 坐标 |
pageY | 触点在页面上的 y 坐标 |
screenX | 触点在屏幕上的 x 坐标 |
screenY | 触点在屏幕上的 y 坐标 |
target | 触摸事件的事件目标 |
这些属性可用于追踪屏幕上的触摸轨迹
11.8.2、手势事件
事件 | 说明 |
---|---|
gesturestart | 一个手指已经放在屏幕上,再把另一个手指放到屏幕上时触发 |
gesturechange | 任何一个手指在屏幕上的位置发生变化时触发 |
gestureend | 其中一个手指离开屏幕时触发 |
手势事件每个event对象都包含所有鼠标事件的公共属性,此外还包含以下两个属性
属性 | 说明 |
---|---|
rotation | 手指变化旋转的度数,负值逆时针,正值顺时针(从0开始) |
scale | 两指之间距离变化(对捏)的程度。开始时为 1,然后随着距离增大或缩小相应地增大或缩小 |