获取元素的方法
document.getElementById()
getElementsByClassName()
getElementsByTagName()
getElementsByName()
querySelector()
querySelectorAll()
注意事项
getElementById()
只能由 document
调用,如果通过其他元素调用会报错,其他方法可由已经获取到的 dom 对象调用
querySelector
和 getElementById
如果获取不到元素会返回 null;getElementsByClassName
、getElementsByTagName
、getElementsByName
、querySelectorAll
如果没有获取到元素也会返回一个伪数组,只不过伪数组长度为 0
事件
focus
: 获得焦点
blur
: 失去焦点
click
: 单击
dblclick
:双击
mouseover/mouseout
: 进入/离开元素
mouseenter/mouseleave
: 进入/离开元素
mousedown
:按下
mouseup
:抬起/释放
mousemove
:移动
keydown/keypress
:按下
keyup
: 释放
属性操作 标签的自定义属性
我们之前讨论的属性,都是 HTML 规范中,标签本来就有的属性,对于标签自定义的一些属性,比较特殊
在 html 页面中,定义一个自定义属性
<div id ="box" aa ="bb" > </div >
在对应的 DOM 对象中是不存在的,在 DOM 对象中只会存在固定的那些属性
var box = document .getElementById ('box' )console .log (box.aa )
attribute 方法
attribute 系列方法用于设置标签的属性,不管是自定义的还是固有的属性
box.getAttribute (属性名) box.setAttribute (属性名, 属性值) box.removeAttribute (属性名)
区别 :
console .log (box.a ) console .log (box.getAttribute ('a' )) box.b = 2 console .log (box.b ) console .log (box.getAttribute ('b' )) box.setAttribute ('c' , 3 ) console .dir (box)console .log (box.c ) console .log (box.getAttribute ('c' )) console .log (box.attributes ) console .log (box.attributes .c )
tab 栏案例 (重点) [案例:获取当前元素的索引]
btns[i].setAttribute ('index' , i) console .log (this .getAttribute ('index' ))btns[i].index = i console .log (this .index )
【案例:tab 栏切换】
标签的内容属性 innerText 和 innerHTML
共同点 : 都是用来获取和设置标签的内容的
区别:
innerHTML 能够识别标签,标签能够生效
innerText 只识别文本,标签会被转义
var div = document .getElementById ('div' )console .log (div.innerText ) console .log (div.innerHTML ) div.innerText = '<h1>嘿嘿</h1>' div.innerHTML = '<h1>嘿嘿</h1>'
浏览器兼容性:指网页在各种浏览器上的显示效果不一致。或者是一些属性和方法在低版本的浏览器中不支持
innerText 是 IE 提出来的属性,因此低版本的火狐浏览器不支持这个属性。
火狐有一个 textContent 属性,效果跟 innerText 一样,但是 IE678 不支持这个属性
书写 innerText 的兼容性代码
function getInnerText (element ) { if (typeof element.innerText === 'string' ) { return element.innerText } else { return element.textContent } }
行内样式操作(style 属性)
标签不仅可以通过 class 属性操作样式 (嵌套样式),还可以通过 style 属性操作样式 (行内样式)。
同样的 DOM 对象可以通过 className 操作样式 (嵌套样式),也可以通过 style 属性操作样 (行内样式)。
css : 嵌套样式 => js : 类名 div.className = ‘red’
css : 行内样式 => js : style 对象 div.style.color = ‘red’
样式属性
style 属性是一个对象,里面存储了所有行内样式的键值对
style 属性只能获取和设置行内样式 ,嵌套样式通过 style 获取不到
如果样式的名字带 -
,比如 background-color ,在 style 对象中使用 backgroundColor => (因为 -
在 js 中不是一个合法的标识符)
style 设置的样式是行内样式,优先级要高于通过 className 设置的样式
<div style ="color:red;background-color:blue;" > 哈哈</div >
var div = document .querySelector ('div' )console .log (div.style )console .log (div.style .color ) div.style .width = '200px' div.style .height = '200px' div.style .fontSize = '100px' div.className = 'box'
getComputedStyle 获取元素计算后的样式
语法: window.getComputedStyle( 获取的元素, 伪类)
伪类 ==> ::after ::before,如果写上了伪类,表示要获取元素的伪类的样式,如果不需要获取的话,该参数写 null
返回值: 返回一个样式对象
var div = document .querySelector ('div' )var ret = window .getComputedStyle (div, null ).fontSize var ret1 = window .getComputedStyle (div, null ).backgroundColor var ret2 = window .getComputedStyle (div, '::after' ).width
关于 body 的样式操作 var bd = document .querySelector ('body' )console .log (bd) console .log (document .body ) document .documentElement document .head document .title
【案例:开关灯案例】
【案例:随机背景颜色案例】
【案例:百度换肤】
关于 cssText (了解)
使用 cssText 可以设置 style 的属性值
<div style ="width: 100px; height: 100px" > 哈哈哈</div > <script > var div = document .querySelector ('div' ) div.style .cssText = 'background:red;color:yellow' </script >
节点操作 (超级重要) 节点属性 (了解) 节点分类:
元素节点、文本节点、属性节点、注释节点
节点常用的属性
节点查找 (重点) 孩子节点 <ul > <li > 导航1</li > <li > 导航2</li > <li > 导航3</li > <li > 导航4</li > </ul > <script > var ul = document .querySelector ('ul' ) console .log (ul.childNodes ) console .log (ul.firstChild ) console .log (ul.lastChild ) console .log (ul.children ) console .log (ul.firstElementChild ) console .log (ul.lastElementChild ) console .log (ul.children [n]) </script >
兄弟节点
nextSibling
: 下一个兄弟节点 (基本不常用)
nextElementSibling
: 下一个兄弟元素(IE678 不兼容)
previousSibling
: 上一个兄弟节点 (基本不常用)
previousElementSibling
: 上一个兄弟元素 有兼容性问题 可以封装一个兼容性方法
<p > 导航1</p > <p class ="p" > 导航2</p > <p > 导航3</p > <script > var p2 = document .querySelector ('.p' ) console .log (p2) console .log (p2.nextSibling ) console .log (p2.nextElementSibling ) console .log (p2.previousSibling ) console .log (p2.previousElementSibling ) </script >
【案例 1:表单校验】
父亲节点
parentNode
: 父节点(没有兼容性问题)
parentElement
: 父元素
添加节点 (重点) appendChild()
注意 : 如果 newChild 已经存在于 DOM 树中,则它会被从原始位置删除
insertBefore()
必须要父节点来调用,newChild 为需要添加的那个节点,refChild 为添加到哪一个节点的前面
没有 insertAfter()
div.appendChild (p) div.insertBefore (p, null ) div.insertBefore (p, s1) div.insertBefore (p, s1.nextElementSibling ) div.insertBefore (p, div.children [0 ]) div.insertBefore (p, div.firstElementChild )
克隆节点 (重点)
克隆出来的节点跟原来的节点没有关系了,修改了也不会相互影响
如果克隆的节点带了 id,我们需要给 id 重新设置一个值,不让 id 冲突
var newNode = div.cloneNode (true )console .log (newNode)
创建节点(3 种方式) (重点) document.write(基本不用) 可以生成新的节点,但是不推荐使用。如果页面已经加载完成了,再用 document.write 写内容的话,会把之前的页面给覆盖掉
原理:页面从上往下加载的时候,会开启一个文档流,当页面加载完,文档流就会关闭。document.write 的本意就是在文档流上写入内容。如果页面没加载完成,文档流还是开着的,document.write 直接在这个文档流上写东西,如果页面加载完成了,还是用 document.write 写东西,会重新开启一个新的文档流,往新的文档流上写东西,旧的文档流就被新的文档流覆盖了。
window .onload = function ( ) { document .write ('呵呵' ) }
innerHTML (偶尔用) innerHTML 也可以创建节点
使用 innerHTML 创建节点时,如果原来有内容的话,会把原先的内容覆盖
慎用:很容易出现效率问题
div.innerHTML = '<h1>哈哈</h1>'
createElement (常用) var div = document .querySelector ('div' )var h1 = document .createElement ('h1' )console .log (h1)h1.style .background = 'red' h1.innerText = '哈' div.appendChild (h1)
删除节点 (重点) div.removeChild (p) p.parentNode .removeChild (p)
【案例 : 节点操作-删除节点】
1. 使用 children 和 TagName => 需要配合 i--2. 使用 querySelectorAll ('li' ) => ok的
[案例 : 许愿墙案例]
功能1 : 克隆10 个tip, 并且随机分布 功能2 : 点击提高层级 功能3 : 点击x, 删除当前tip 功能4 : 双击tip头部, 删除当前tip
替换节点 parentNode.replaceChild (newChild, oldChild)
注意 : 如果 newChild 已经存在于 DOM 树中,则它会被从原始位置删除
节点操作综合案例 【动态生成表格】
BOM
BOM(Browser Object Model):浏览器对象模型,提供了一套操作浏览器功能的工具
重点 :定时器、 offset 系列
window
window 对象是一个全局对象,也可以说是 JavaScript 中的顶级对象
所有定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法
像 document、alert()、console.log() 这些都是 window 的属性,其实 BOM 中基本所有的属性和方法都是 window 的
window 对象下的属性和方法调用的时候可以省略 window
.onload(掌握)
window.onload 事件会在 窗体加载完成 后执行,通常我们称之为入口函数。
window .onload = function ( ) { }
如果有图片加载,那么代码一定要写到 window.onload 里面,否则会出现图片没有加载完成,获取到的宽度和高度不对的情况。
浏览器会对页面的加载做优化,在加载图片的时候,图片的引入会延迟。
<img src="./01.png" alt="" > window .onload = function ( ) { var img = document .querySelector ('img' ) console .log (img.width ) console .log (img.height ) }
.open() 与 .close() (了解)
var newWin = window .open ('http://www.baidu.com' , '_blank' , 'width=300,height=300' )
newWin.close () window .close ()
延时器与定时器 (重点) setTimeout 延时器
可以在延迟一定时间后执行指定的代码
设置延时器
var timer = setTimeOut (function ( ) { }, 1000 )
清除延时器
setInterval 定时器
setInterval 方法重复调用一个函数或执行一个代码段,在每次调用之间具有固定的时间间隔。 (每隔一段时间执行一段代码)
定时器除非清除,否则会一直执行下去。
设置定时器
var timer = setInterval (function ( ) { }, 1000 )
清除定时器
案例 【短信验证码案例.html】
location 对象
location 对象也是 window 的一个属性
location 其实对应的就是浏览器中的地址栏
常用属性和方法
location.href : 控制地址栏的地址,实现页面跳转
document .onclick = function ( ) { location.href = 'http://www.baidu.com' }
[案例 : 注册成功,3 秒后跳转]
页面跳转:
location.href = 'url地址'
location.assign('url地址')
location.replace('url地址')
(不记录历史)
location.reload() 让页面重新加载
document .onclick = function ( ) { location.reload () }
location 的其他值
http://www.bbb.com:8080/index.html?id=666&psd=123#xxx
location.hash //哈希值 其实就是锚点 ==> #xxx
location.host //服务器 服务器名+端口号 => www.bbb.com:8080
location.hostname //服务器名 => www.bbb.com
location.pathname //路径名 => index.html
location.port //端口 => 8080
location.protocol //协议 => http
location.search //参数 => ?id=666&psd=123
其他对象
history.back () history.go (-1 ) history.forward () history.go (1 )
console .log (screen.width ) console .log (screen.height ) console .log (screen.availWidth ) console .log (screen.availHeight )
缓动动画 缓动动画初体验 动画公式 :
var step = (target - current) / 10 current += step
[案例演示 : ]
1. 三步走 - 获取当前位置 - 累加小碎步 - 重复赋值回去 2. 定时器
缺点 : 打开控制台, 查看盒子的结构行内样式 left, 发现并没有跑到 400px, 只能跑到 396.4/395.5
原因 : offsetLeft 获取值的时候, 只会获取整数 , (对小数部分会四舍五入,整数有时候往上取整,有时候往下取整); 可以在获取的 offset 地方打印查看
缓动动画 - 移动 400 位置 动画公式 :
var step = (target - current) / 10 step = Math .ceil (step) current += step
案例演示 注意点 :
1. 查看位置 : left有时候为 395.5 / 396.4 2. 打印: offsetLeft => 395 / 396 3. step为整数 往上取整
缓动动画 - 回到 0 点位置 动画公式 :
var step = (target - current) / 10 step = Math .floor (step) current += step
案例演示注意点 :
1. 先把盒子 设置 left : 400px 位置; 回到0 位置2. 查看位置 : left有时候为 4.5 3. 打印: offsetLeft => 5 4. step为整数 往下取整
缓动动画 - 封装函数 function animate (element, target ) { if (element.timerId ) { clearInterval (element.timerId ) } element.timerId = setInterval (function ( ) { var current = element.offsetLeft var step = (target - current) / 10 step = step > 0 ? Math .ceil (step) : Math .floor (step) current += step element.style .left = current + 'px' if (current == target) { clearInterval (element.timerId ) } }, 15 ) }
[案例 : 筋斗云]
[案例:开机提示关闭]
事件对象 事件对象的概述
在触发某个事件 的时候,都会产生一个事件对象 Event ,这个对象中包含所有与事件相关的一些信息 ,包括触发事件的元素,事件的类型以及其他与事件相关的信息
鼠标 事件触发 时,事件对象中会包含鼠标的位置信息 。
键盘 事件触发 时,事件对象中会包含按下的键相关的信息 。
获取事件对象 现代浏览器获取 : (掌握)
btn.onclick = function (e ) { console .log (e) }
低版本浏览器 (ie678): (了解)
btn.onclick = function ( ) { console .log (window .event ) }
兼容性 :
btn.onclick = function (e ) { e = e || window .event }
事件对象的常用属性
事件对象中有很多很多的属性,但是很多属性并不常用。我们经常用到的是鼠标位置信息 和键盘码 相关的信息
鼠标位置信息
clientX
与 clientY
: 相对于浏览器可视区 左上角的位置(不随滚动条滚动而改变)
pageX
与 pageY
:相对于网页内容 (文档 document)左上角的位置
screenX
与 screenY
:相对于屏幕 左上角的位置
offsetX
与 offsetY
:鼠标相对于事件源 左上角的位置
document .onmousemove = function (e ) { console .log (e.clientX , e.clientY ) console .log (e.pageX , e.pageY ) console .log (e.screenX , e.screenY ) }
[案例 : 拖拽案例]
键盘码
注册事件的两种方式 on + 事件名称
onclick、onmouseover 这种 on+事件名称的方式注册事件几乎所有的浏览器都支持
box.onclick = function ( ) { } box.onclick = null
on+事件名称注册事件的缺点:同一个元素同一类型的事件,只能注册一个,如果注册了多个,会出现覆盖问题
addEventListener
现代浏览器支持的注册事件的新方式,这种方式注册的事件不会出现覆盖问题
addEventListener 的语法
element.addEventListener (type, fn, useCapture) btn.addEventListener ('click' , function ( ) { console .log ('哈哈' ) })
removeEventListen 的语法
element.removeEventListener (type, fn) btn.removeEventListener ('click' , fn)
低版本浏览器兼容问题: (了解)
IE678 不支持 addEventListener 与 removeEventListen 两个方法,但是支持 attachEvent 与 detachEvnet
attachEvent 的用法:
attachEvent (type, fn)btn.attachEvent ('onclick' , function ( ) { alert ('哈哈' ) })
detachEvent 的用法:
兼容性封装(了解) function addEvent (element, type, fn ) { if (element.addEventListener ) { element.addEventListener (type, fn) } else if (element.attachEvent ) { element.attachEvent ('on' + type, fn) } else { element['on' + type] = fn } } function removeEvent (element, type, fn ) { if (element.removeEventListener ) { element.removeEventListener (type, fn, false ) } else if (element.detachEvent ) { element.detachEvent ('on' + type, fn) } else { element['on' + type] = null } }
事件流 事件冒泡 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为冒泡
说白了就是:当我们触发了子元素的某个事件后,父元素对应的事件也会触发
on 创建的事件默认为冒泡,无法修改
[案例 : 弹窗案例]
阻止事件冒泡 e.stopPropagation()
box.onclick = function (e ) { e.stopPropagation () } box.addEventListener ('click' , function ( ) {}, 参数1 )
event.stopImmediatePropagation
阻止事件冒泡并且阻止相同事件的其他侦听器被调用 如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。如果其中某个监听函数执行了 event.stopImmediatePropagation()
方法,则当前元素剩下的监听函数将不会被执行
阻止事件冒泡的兼容性封装
function stopPropagation (e ) { if (e && e.stopPropagation ) { e.stopPropagation () } else { window .event .cancelBubble = true } }
事件捕获 事件冒泡是 ie 提出来的
路径 : 触发事件的目标元素(son) > you > father > body > document
事件捕获是火狐提出来的
路径 : document > body > father > you > 触发事件的目标元素 (son)
解析 : 事件的处理将从 DOM 层次的根开始,而不是从触发事件的目标元素开始,事件被从目标元素的所有祖先元素依次往下传递
arr[i].addEventListener ( 'click' , function ( ) { }, true )
事件流的三个阶段
事件的捕获阶段
事件的目标阶段(触发自己的事件)
事件的冒泡阶段
事件有三个阶段 :
捕获事件和冒泡事件都存在的话,首先发生的是捕获阶段,然后是目标阶段,最后才是冒泡阶段
addEventListener 第三个参数为是否捕获
如果为 true 时,表示该事件在捕获阶段发生
如果为 false 时,表示该事件在冒泡阶段发生
某一个事件只会执行一次
三大系列 offset 系列 (重要)
offset 系列用于用于获取元素自身的大小和位置 ,在 webapi 中有广泛应用 offset 系列主要有:offsetHeight、offsetWidth、offsetParent、offsetLeft、offsetTop
offsetHeight 与 offsetWidth
获取元素真实的高度和宽度 (内容大小 + border + padding)(关注盒子本身,不关注盒子内部内容)
获取到的是数值类型,方便计算
offsetHeight 与 offsetWidth 是只读属性,不能设置
style.height 与 style.width
只能获取和设置行内样式
不包括内边距、边框和外边距
获取到的是字符串类型,需要转换
offsetParent
获取离当前元素最近的定位父元素 (absolute、relative),如果没有,那就找 body
parentNode : 父节点(没有兼容性问题)
parentElement : 父元素
offsetLeft 与 offsetTop
获取元素自身与 offsetParent 真实的距离
获取到的是数值类型,方便计算
只读属性,只能获取,不能设置
style.left 与 style.top
只能获取和设置行内样式
获取到的是字符串,需要转换
scroll 系列是用来获取盒子内容的大小和位置
scroll 系列主要有 : scrollWidth、scrollHeight、scrollLeft、scrollTop
scrollWidth 与 scrollHeight
scrollWidth 与 scrollHeight 是盒子内容的宽度和高度。与盒子大小无关,仅仅与盒子的内容 有关系(padding + 内容)
如果内容没有溢出,scrollHeight 就是盒子高度 (scrollWidth 同理) => 与 clientHeight、clientWidth 相同
如果内容超过盒子,scrollHieght 就是内容高度 (scrollWidth 同理)
scrollTop
scrollTop 用于获取内容垂直滚动的像素数。如果没有滚动条,那么 scrollTop 值是 0
内容超过盒子,盒子设置 overflow: scroll 就可出现滚动条
此属性是可读写的
scrollLeft
scrollLeft 用于获取内容水平滚动的像素数
此属性是可读写的
浏览器切忌这种出现水平滚动条,用户体验极差,避免
scrollX 与 scrollY
onscroll 事件
对于有滚动条的盒子,可以使用 onscroll 注册滚动事件,每滚动一像素,就会触发该事件
var div = doucment.getElementById ('div' )div.onscroll = function ( ) { console .log (div.scrollLeft ) console .log (div.scrollTop ) }
场景 : 获取页面被卷去的高度和宽度
通常来说,scroll 家族用的最多的地方就是用来获取页面 被卷去的高度 ,非常的常用
对于老式的浏览器,需要获取 html 或者 body 的 scrollTop
对于现在浏览器,使用 window.pageYOffset 进行获取
页面被卷去的高度和宽度的兼容性封装
document .onscroll = function ( ) { var scrollTop = window .pageYOffset || document .documentElement .scrollTop || document .body .scrollTop || 0 var scrollLeft = window .pageXOffset || document .documentElement .scrollLeft || document .body .scrollLeft || 0 console .log (scrollLeft, scrollTop) }
[案例 : 固定导航案例]
client 家族
clien t 家族用于获取盒子可视区的大小 (内容 + padding)
client 家族有 clientWidth、clientHeight、clientLeft、clientTop
clientWidth、clientHeight 可视区宽高
clientTop 与 clientLeft 完全没有用,他们就是 borderTop 与 borderLeft
onresize 事件:onresize 事件会在窗口被调整大小的时候发生。
window .onresize = function ( ) { }
场景 : client 系列一般用来获取页面的可视区宽高
低版本浏览器 : 获取的 html 和 body
高版本的浏览器 : window.innerWidth (掌握)(只读属性)
window .onresize = function ( ) { var W = window .innerWidth || document .documentElement .clientWidth || document .body .clientWidth console .log (W) var H = window .innerHeight || document .documentElement .clientHeight || document .body .clientHeight console .log (H) }