一、DOM
DOM,全称是Document Object Model 文档对象模型 DOM的本质是一棵节点树
1. 节点
节点:Node,是构成HTML文档最基本的单元 通常可以分为四类:
文档节点:整个HTML文档 元素节点:html中的标签 属性节点:元素的属性 文本节点:标签中的文本内容
2. 节点的属性
- nodeName nodeType nodeValue 文档节点 #document 9 null 元素节点 标签名 1 null 属性节点 属性名 2 属性值 文本节点 #text 3 文本内容
3. 获取DOM节点的方法
方法 描述 补充 document.getElementById() 通过id获取一个
元素 在实际开发中较少使用,选择器中多用class, id一般只用在顶级层存在 不能太过依赖id document.getElementsByTagName(); 通过标签名获取元素集合 返回符合tagName的所有元素的类数组对象,尽管只找到一个元素也会存到类数组 document.getElementsByClassName(); 通过类名获取元素集合 返回符合className的所有元素的类数组对象 document.getElementsByName(); name属性值 一般不用 document.querySelector(); css选择符模式 返回与该模式匹配的第一个
元素,结果为一个元素;如果没找到匹配的元素,则返回null document.querySelectorAll() css选择符模式 返回与该模式匹配的所有
元素,结果为一个类数组
4. 节点间的关系
关系 考虑所有节点 只考虑元素节点 子节点 childNodes children 父节点 parentNode parentNode 第一个子节点 firstChild firstElementChild 最后一个子节点 lastChild lastElementChild 前一个兄弟节点 previousSibling previousElementSibling 后一个兄弟节点 nextSibling nextElementSibling
< div class = " box" >
< p class = " item" > 段落1</ p>
< p class = " item" > 段落2</ p>
< p class = " item" > 段落3</ p>
</ div>
< script>
let box = document. querySelector ( '.box' )
console. log ( box. childNodes)
console. log ( box. children) ;
console. log ( box. firstChild)
console. log ( box. firstElementChild) ;
console. log ( box. lastChild) ;
console. log ( box. lastElementChild) ;
</ script>
4.1 封装常见的节点关系函数
返回元素的所有子元素节点(兼容到IE6)
function getChildren ( node ) {
let children = [ ]
for ( let i = 0 ; i < node. childNodes. length; i++ ) {
if ( node. childNodes[ i] . nodeType === 1 ) {
children. push ( node. childNodes[ i] )
}
}
return children
}
获取元素前一个兄弟元素节点,类似于 previousElementSibling
function getElementPrevSibling ( node ) {
while ( node. previousSibling !== null ) {
if ( node. previousSibling. nodeType === 1 ) return node. previousSibling
node = node. previousSibling
}
}
获取所有兄弟元素节点
function getAllElementSibling ( node ) {
let prevs = [ ]
let nexts = [ ]
while ( node. previousSibling !== null ) {
if ( node. previousSibling. nodeType === 1 ) {
prevs. unshift ( node. previousSibling)
}
node = node. previousSibling
}
while ( node. nextSibling !== null ) {
if ( node. nextSibling. nodeType === 1 ) {
nexts. push ( node. nextSibling)
}
node = node. nextSibling
}
return prevs. concat ( nexts)
}
5. 节点的操作
5.1 改变元素节点的内容
属性 说明 innerHTML 以HTMl语法
设置节点内容 innerText 以纯文本形式
设置节点内容
5.2 改变css样式
语法:元素.style.属性名 = '属性值'
,属性名是驼峰
格式的
let box = document. querySelector ( '.box' )
box. style. color = 'skyblue'
box. style. fontSize = '18px'
5.3 改变元素节点的HTML属性
更改标准W3C属性(如src、herf等):元素.属性名 = '属性值'
let img = document. getElementById ( 'img' )
img. src = 'https://img.mukewang.com/szimg/620b43350928ec7140000576.jpg'
更改非标准W3C属性,要使用 setAttribute、getAttribute
5.4 节点的创建、移除、克隆
方法 说明 document.createElement(‘tagName’) 创建一个指定tagName的HTML元素(孤儿节点) 父节点.appendChild(孤儿节点) 将孤儿节点插入父节点的最后,使其成为最后一个子节点 父节点.insertBefore(孤儿节点,标杆节点) 将孤儿节点插入到标杆节点前面,使其成为标杆节点的前一个兄弟节点 新父节点.appendChild(已经有父亲的节点) 将节点移动
到新父节点 新父节点.insertBefore(已有父亲的节点, 标杆子节点) 将节点移动
到新父节点 父节点.removeChild(子节点) 将子节点从父节点中删除 cloneNode() 克隆节点,克隆出的节点是孤儿节点。参数表示是否要深度克隆,如果参数为true表示该节点及其后代节点都会被克隆,参数为false表示只克隆节点本身
6. DOM 性能优化
对DOM进行缓存 将频繁的操作改为一次操作或少量操作
二、BOM
BOM(Browser Object Model,浏览器对象模型),JS与浏览器窗口交互的接口
1. window 对象
window对象,是当前JS脚本运行所在的窗口 window.document对象,即document对象 全局变量
是window对象的属性,多个JS文件之间共享全局作用域,不会有作用域隔离内置函数
一般都是window的方法,如setInterval()、alert()
1.1 窗口尺寸相关属性
属性 描述 innerHeight 浏览器窗口内容区的高度,包含水平滚动条 innerWidth 浏览器窗口内容区的宽度,包含垂直滚动条 outerHeight 浏览器窗口的外部高度 outerWidth 浏览器窗口的外部宽度 document.documentElement.clientHeight 窗口不包含滚动条的高度 document.documentElement.clientWidth 窗口不包含滚动条的宽度 scrollY 垂直方向滚动的距离(只读) document.documentElement.scrollTop 垂直方向滚动的距离 offsetTop 当前元素到定位祖先元素的垂直距离
scrollTop = window. screenY || document. documentElement. scrollTop
1.2 resize事件
窗口大小改变后会触发resize事件 window.onresize
或 window.addEventListener('resize')
绑定窗口改变事件
1.3 scroll事件
窗口滚动时会触发scroll事件 window.onscroll
或 window.addEventListener('scroll')
绑定scroll事件
2. Navigator 对象
window.navigator 包含浏览器的相关属性和标识
属性 说明 appName 浏览器官方名称 appVersion 浏览器版本 userAgent 浏览器用户代理(内核信息和封装壳信息等) platform 用户操作系统
3. history对象
window.hstory 浏览器会话历史 浏览器回退:history.back()
或 history.go(-1)
4.location 对象
window.location 当前所在的网址,可以通过给该属性赋值进行页面跳转 window.location.reload()
重新加载当前页面,可以设置参数,当参数为 true 表示强制从服务器加载widow.location.search
给当前浏览器的get请求查询参数
5. 案例一 —— 返回顶部
<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< meta http-equiv = " X-UA-Compatible" content = " IE=edge" >
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" >
< link rel = " stylesheet" href = " https://at.alicdn.com/t/font_3279057_d1pzygibna.css" >
< title> Document</ title>
< style>
html {
height : 5000px;
}
.top-box {
width : 50px;
height : 50px;
text-align : center;
line-height : 50px;
border-radius : 50%;
background-color : #fff;
box-shadow : 0 2px 4px 0 rgba ( 0, 0, 0, .05) ;
cursor : pointer;
position : fixed;
right : 20px;
bottom : 20px;
display : none;
}
</ style>
</ head>
< body>
< div class = " top-box" >
< span class = " iconfont icon-top" > </ span>
</ div>
< script>
let oTop = document. querySelector ( '.top-box' )
window. onscroll = function ( ) {
let height = document. documentElement. clientHeight
let scrollTop = window. screenY || document. documentElement. scrollTop
if ( height < scrollTop) {
oTop. style. display = 'block'
} else {
oTop. style. display = 'none'
}
}
let timer
oTop. onclick = function ( ) {
clearInterval ( timer)
timer = setInterval ( ( ) => {
document. documentElement. scrollTop -= 200
if ( document. documentElement. scrollTop <= 0 ) clearInterval ( timer)
} , 20 ) ;
}
</ script>
</ body>
</ html>
6. 案例 —— 楼层导航
< ! DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
< meta http- equiv= "X-UA-Compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1.0" >
< title> Document< / title>
< style>
* {
padding: 0 ;
margin: 0 ;
}
li {
list- style: none;
}
body {
font: 12 px/ 1.5 Microsoft YaHei, Heiti SC , tahoma, arial, Hiragino Sans GB , "\5B8B\4F53" , sans- serif;
color: #666 ;
}
. right- menu {
position: fixed;
right: 20 px;
top: 100 px;
z- index: 19 ;
width: 50 px;
background- color: #fff;
box- shadow: 0 2 px 4 px 0 rgba ( 0 , 0 , 0 , .05 ) ;
padding: 5 px;
text- align: center;
}
. menu- item {
cursor: pointer;
line- height: 30 px;
}
. menu- item. active {
color: tomato;
}
. line {
width: 30 px;
height: 1 px;
margin: 0 px auto;
background- color: #eee;
}
. content- part {
width: 800 px;
height: 500 px;
background- color: tomato;
margin: 30 px auto;
font- size: 20 px;
color: #fff;
}
< / style>
< / head>
< body>
< ! -- 楼层导航 -- >
< ul class = "right-menu" >
< li data- n= "导航1" class = "menu-item active" > 导航1 < / li>
< li class = "line" > < / li>
< li data- n= "导航2" class = "menu-item" > 导航2 < / li>
< li class = "line" > < / li>
< li data- n= "导航3" class = "menu-item" > 导航3 < / li>
< li class = "line" > < / li>
< li data- n= "导航4" class = "menu-item" > 导航4 < / li>
< li class = "line" > < / li>
< li data- n= "导航5" class = "menu-item" > 导航5 < / li>
< / ul>
< ! -- 内容区 -- >
< div class = "container" >
< div data- n= "导航1" class = "content-part" > 内容区1 < / div>
< div data- n= "导航2" class = "content-part" > 内容区2 < / div>
< div data- n= "导航3" class = "content-part" > 内容区3 < / div>
< div data- n= "导航4" class = "content-part" > 内容区4 < / div>
< div data- n= "导航5" class = "content-part" > 内容区5 < / div>
< / div>
< script>
let oMenu = document. querySelector ( '.right-menu' )
oMenu. onclick = function ( e ) {
if ( e. target. tagName. toLowerCase ( ) === 'li' ) {
let n = e. target. getAttribute ( 'data-n' )
let contentPart = document. querySelector ( ` .content-part[data-n= ${ n} ] ` )
document. documentElement. scrollTop = contentPart. offsetTop
}
}
let menuArr = [ ]
let conParts = document. querySelectorAll ( '.content-part' )
for ( let i = 0 ; i< conParts. length; i++ ) {
menuArr. push ( conParts[ i] . offsetTop)
}
menuArr. push ( Infinity )
let curFloor = - 1
let lis = document. querySelectorAll ( '.menu-item' )
window. onscroll = function ( ) {
let scrollTop = window. screenY || document. documentElement. scrollTop
for ( let i = 0 ; i < menuArr. length; i++ ) {
if ( scrollTop >= menuArr[ i] && scrollTop < menuArr[ i+ 1 ] ) break
if ( curFloor != i) {
curFloor = i
for ( let j = 0 ; j < lis. length; j++ ) {
if ( j === i) {
lis[ j] . className = 'menu-item active'
} else {
lis[ j] . className = 'menu-item'
}
}
}
}
}
< / script>
< / body>
< / html>
三、事件
1. DOM0 级事件监听: onxxx
直接在HTML标签内部书写
< button onclick = " alert(' hello,你找我有啥事啊?' )" > 点我</ button>
通过绑定处理函数的形式
< button class = " btn" id = " btn" > 点我</ button>
< script>
let btn = document. querySelector ( '.btn' )
btn. onclick = function ( ) {
alert ( '你好!!' )
}
</ script>
1.1 常见的鼠标事件
事件 描述 onclick 单击 ondblclick 双击 onmousedown 按下鼠标 onmouseup 松开鼠标 onmousemove 移动鼠标 onmouseenter 鼠标移入(相似事件onmouseover) onmouseleave 鼠标移出(相似事件onmouseout) onmousewheel 鼠标滚动
onmouseenter和onmouseover 都表示鼠标移入,但onmouseenter 不会冒泡,onmouseover 会冒泡
1.2 常见的键盘事件
事件 描述 onkeypress 按下键盘按钮,不能识别系统按钮,如:箭头键、功能键等 onkeydown 按下键盘按钮,可以识别系统按钮,且先于keypress onkeyup 按键被松开
1.3 常见的表单事件
事件 描述 onchange 内容改变 onfocus 获得焦点时 onblur 失去焦点 onsubmit 提交表单 onreset 重置表单
1.4 常见的页面事件监听
事件 描述 onload 页面或图像加载完毕 onunload 退出页面
2. DOM2 级事件监听:addEventListener
2.1 事件传播
事件传播是先从外到内(捕获阶段
),再从内到外(冒泡阶段
) onxxx
只能监听冒泡阶段
2.2 addEventListener
语法: 元素.addEventListener('事件名',function(){},true)
第一个参数是要触发的事件,此时不加 on 第二个参数是事件处理函数 第三个参数为布尔值,true表示监听捕获阶段,false监听冒泡阶段 最内部元素不在区分捕获和冒泡,会先执行前面的监听,后执行后面的监听
同名
时,DOM0 中后面的会覆盖前面的;DOM2 级会按顺序执行
3. 事件对象
事件处理函数中提供了一个形参(e 或 event
),该形参封装了本次事件的细节,称为“事件对象”
3.1 鼠标位置的相关属性
属性 描述 clientX 鼠标指针相对于浏览器
的水平坐标 clientY 鼠标指针相对于浏览器
的垂直坐标 pageX 鼠标指针相对于整张网页
的水平坐标 pageY 鼠标指针相对于整张网页
的垂直坐标 offsetX 鼠标指针相对于事件源元素
的水平坐标 offsetY 鼠标指针相对于事件源元素
的垂直坐标
3.2 键盘事件中的相关属性
属性 描述 e.charCode 返回 onkeypress 事件中用户输入字符的字符码 e.keyCode onkeydown、onkeyup中,用户按下的键码
字符 字符码 数字 0 ~ 9 48 ~ 57 大写字母 A ~ Z 65 ~ 90 小写字母 a ~ z 97 ~ 122
按键 键码 数字 0 ~ 9 48 ~ 57 不分大小写的字母 a ~ z 65 ~ 90 方向键 ← ↑ → ↓ 37、38、39、40 回车键 13 空格键 32
< body>
< div id = " box" class = " box" > </ div>
< script>
let box = document. getElementById ( 'box' )
let l = 200
let t = 50
document. onkeydown = function ( e ) {
switch ( e. keyCode) {
case 37 :
l -= 5
break
case 38 :
t -= 5
break
case 39 :
l += 5
break
case 40 :
t += 5
break
}
box. style. left = l + 'px'
box. style. top = t + 'px'
}
</ script>
</ body>
3.3 e.perventDefault()
3.4 e.stopPropagation()
4. 事件委托
事件委托:利用事件冒泡
机制,将后代
元素的事件委托给祖先
元素 事件委一般要和 e.target
搭配使用
属性 描述 target 触发此事件最早的元素,即“事件源元素” currentTarget 事件处理程序附加到的元素
应用场景:批量事件监听、新增元素动态绑定事件 事件委托不能委托给不冒泡的(如onmouseenter) 使用事件委托时,最内层元素不能再有额外元素
5. 定时器和延时器
5.1 定时器
setInterval(),定时器可以重复调用一个函数,每次调用之间的时间间隔固定 语法:setInterval(()=>{},time)
,第一个参数是函数,第二个参数是时间间隔,单位为毫秒,1000ms = 1s,从第三个参数开始表示要传入第一个函数的参数 清除定时器: clearInterval()
< h3 class = " info" > 0</ h3>
< button class = " btn start-btn" > 开始</ button>
< button class = " btn end-btn" > 暂停</ button>
< script>
let oInfo = document. querySelector ( '.info' )
let oStart = document. querySelector ( '.start-btn' )
let oEnd = document. querySelector ( '.end-btn' )
let a = 0
let timer
oStart. onclick = function ( ) {
clearInterval ( timer)
timer = setInterval ( ( ) => {
oInfo. innerHTML = ++ a
} , 1000 )
}
oEnd. onclick = function ( ) {
clearInterval ( timer)
}
</ script>
5.2 延时器
setTimeout(),到达指定时间后会执行一次,不再重复 clearTimeout(),清除延时器
5.3 案例 —— 无缝连续滚动特效动画
< ! DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
< meta http- equiv= "X-UA-Compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1.0" >
< title> Document< / title>
< style>
* {
padding: 0 ;
margin: 0 ;
}
li {
list- style: none;
}
. container {
width: 300 px;
height: 50 px;
margin: 50 px auto;
overflow: hidden;
}
. animation- box {
width: 2200 px;
height: 500 px;
margin: 0 auto;
position: relative;
}
. animation- item {
width: 50 px;
height: 30 px;
line- height: 30 px;
text- align: center;
border: 1 px solid tomato;
float: left;
margin- right: 10 px;
}
< / style>
< / head>
< body>
< div class = "container" >
< ul class = "animation-box" >
< li class = "animation-item" > 1 < / li>
< li class = "animation-item" > 2 < / li>
< li class = "animation-item" > 3 < / li>
< li class = "animation-item" > 4 < / li>
< li class = "animation-item" > 5 < / li>
< / ul>
< / div>
< script>
let container = document. querySelector ( '.container' )
let listBox = document. querySelector ( '.animation-box' )
listBox. innerHTML += listBox. innerHTML
let left = 0
let timer
function move ( ) {
clearInterval ( timer)
timer = setInterval ( ( ) => {
left -= 4
if ( left < - 300 ) left = 0
listBox. style. left = left + 'px'
} , 50 )
}
move ( )
container. onmouseenter = function ( ) {
clearInterval ( timer)
}
container. onmouseleave = function ( ) {
move ( )
}
< / script>
< / body>
< / html>