本篇整理了一下DOM的一些基础知识,目前记录的知识还比较基础,更深的知识尚未整理。往后将继续学习和补充。
如有记录得不对的地方,欢迎探讨。
文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
元素操作主要有创建、增、删、改、查
document.write():如果页面文档流加载完毕再调用它,会导致页面重绘;(实际开发中不常用)
innerHTML:是将内容写入某个DOM节点,不会导致页面重绘;
createElement:不会导致页面重绘;
经典面试题:innerHTML 和 createElement 的效率哪一个更高?
innerHTML创建多个元素效率更高(不要以拼接字符串的方式,以数组存储字符串(push),再填入innerHTML(join))
createElement 创建多个元素的效率稍微低一点,但是结构更为清晰。
node.appendChild(child):后面追加元素
node.insertBefore(要插入的元素child, 指定元素):在指定元素前插入元素
node.cloneNode():
node.removeChild(child):删除一个子节点,返回删除的节点
主要修改的是dom元素的属性,内容,表单的值,元素样式等。
DOM提供的API:
getElementById():参数为字符串,需要加引号,找不到元素则返回null
getElementsByTagName()
getElementsByClassName()
H5提供的新方法:
querySelector()
querySelectorAll()
节点操作:
网页中所有内容都是节点(标签节点、属性节点、文本节点、注释节点等)
一般来说,节点至少拥有nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)
nodeType:
元素节点:nodeType = 1;
属性节点:nodeType = 2;
文本节点:nodeType = 3;(包括文字、空格、换行)
父级节点:node.parentNode
子节点:
node.childNodes(标准)
返回结果中包含元素节点、文本节点(如空格和换行)等
若想只获得元素节点,可通过for循环+nodeType判断获得
node.children(非标准)
我们往往只想获取子元素节点,不需要你把换行这种文本节点都获取过来
获取所有子元素节点(不包含文本节点),实际开发中常用
node.firstChild 和 node.lastChild
node.firstElementChild 和 node.lastElementChild
node.children[0] 和 node.children[node.children.length - 1]
兄弟节点:
node.nextSibling:下一个兄弟节点
node.previousSibling:上一个兄弟节点
显而易见,上面两种获取方式也是会将除元素节点之外的节点获取过来的,于是有了另外两种获取方式:
不过后面两种同样存在兼容性要求,解决的思路是自行封装一个兼容性函数。
获取属性
设置属性
ele.Attr = 'value’
ele.setAttribute(‘Attr’, ‘value’)
需要注意的是修改类名的时候,两种方法对类名属性要求不同:
这是由于在js中,class为保留字
移除属性
获取自定义属性
ele.getAttribute(‘data-attr’):兼容性好
ele.dataset.attr 或 ele.dataset[‘attr’]
dataset 是一个对象, 存放所有以data开头的自定义属性
dataset只能获取“data-”开头的属性
如果自定义属性中有多个链接的单词,JS中采用驼峰命名法
传统注册方式:
ele.onclick = function(){}
事件监听方式:
ele.addEventListener('click', function(){}, false)
ie9以下:
ele.attachEvent('onclick', function(){})
传统方式:
e.onclick = null
事件监听:
e.removeEventListener('click', fn)
ie9以下:
e.detachEvent('onclick', fn)
常用的鼠标事件:
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
除此之外,还有一些常用的:
禁止鼠标右键菜单:(主要用于程序员取消默认的上下文菜单)
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
禁止鼠标选中:
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
常用的键盘事件:
键盘事件 | 触发条件 |
---|---|
onkeyup | 键盘弹起触发 |
onkeydown | 键盘按下触发 |
onkeypress | 键盘按下触发 |
onkeydown 和 onkeypress 区别:
事件调用顺序:keydown ---- keypress ---- keyup
事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点间按照特定的顺序传播,这个传播过程就是DOM事件流。
比如我们给一个div注册了事件,DOM事件流分为三个阶段:
注意:
事件对象是事件的一系列信息数据的集合,与具体的事件有关
ie9以下只识别window.event,处理:
e = e || window.event
e.target 和 this 的区别:
e.target 返回的是触发事件的对象/元素(点击了谁)
this 返回的是绑定事件的对象/元素
如:
<ul>
<li>1li>
<li>2li>
<li>3li>
ul>
给ul绑定click事件,但点击的是li,则:e.target 返回的是li,this返回ul
currentTarget用法与this一样,且有兼容性要求,因此不常用,用this就可以了
e.type返回事件类型
阻止默认行为:e.preventDefault()
阻止事件冒泡:e.stopPropagation()
鼠标事件中:
键盘事件中:keyCode可以获取按下键的ASCII值,可用于判断按下了什么键
描述(面试):不是每个子节点单独设置事件监听器,而是把事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window。
BOM把「浏览器」当做一个「对象」来看待
BOM 学习的是浏览器窗口交互的一些对象
BOM 是浏览器厂商在各自浏览器上定义的,兼容性较差
BOM由一系列相关的对象构成,并且每个对象都提供了很多方法和属性。
window对象是浏览器的顶级对象,它具有双重角色:
它是JS访问浏览器窗口的一个接口
它是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性和方法
在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert()、prompt()等。
注意:window下有个特殊的属性——window.name
window.onload = function() {}
window.addEventListener('load', function(){})
window.onload 是窗口 (页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等),就调用的处理函数。
注意:
有了 window.onload 就可以把 JS 代码写到页面元素的上方,因为 onload 是等页面内容全部加载完毕,再去执行处理函数。
window.onload 传统注册事件方式 只能写一次,如果有多个,会以最后一个 window.onload 为准。
如果使用 addEventListener 则没有限制
document.addEventListener('DOMContentLoaded', function(){})
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。
Ie9以上才支持
如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded 事件比较合适。
只要窗口大小改变就触发
我们经常利用这个事件完成响应式布局。可以通过 window.innerWidth 获取当前屏幕的宽度
setTimeout执行函数的this指向window
一般会给定时器添加标识符(方便后面清除):
let timer = setTimeout(function() {
console.log(1)
}, 1000)
清除定时器:
window.clearTimeout(timer)
window可以省略
setInterval执行函数的this指向window
一般会给定时器添加标识符(方便后面清除)
清除定时器:
window.clearInterval(timer)
window可以省略
window 对象给我们提供了一个 location 属性用于获取或设置窗体的 URL,并且可以用于解析 URL 。 因为这个属性返回的是一个对象,所以我们将这个属性也称为 location 对象。
location对象属性 | 返回值 |
---|---|
location.href | 获取或设置整个URL |
loaction.host | 返回主机/域名 |
location.port | 返回端口号,如果未写返回空字符串 |
location.pathname | 返回路径 |
location.search | 返回参数 |
location.hash | 返回片段 #后面的内容 |
location对象方法 | 返回值 |
---|---|
location.assign() | 和href一样,可以跳转页面(也称为重定向页面),有历史记录,可以返回和前进 |
location.replace() | 替换当前页面,没有历史记录,不能返回和前进 |
location.reload() | 刷新页面,可带参数false或true,默认为false,表示刷新,相当于F5;true表示强制刷新,相当于ctrl+F5 |
navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。
下面前端代码可以判断用户那个终端打开页面,实现跳转:
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = ""; //手机
} else {
window.location.href = ""; //电脑
}
history接口是HTML5新增的, 它有五种模式改变URL而不刷新页面:
history.pushState()
history.pushState({},'','/foo')
history.replaceState()
history.replaceState({},'','/foo/bar')
history.go()
history.go(-1)//后退一个页面
history.go(1)//前进一个页面
history.back() 等价于 history.go(-1)
history.forward() 等价于 history.go(1)
screen对象在编程中用处不大,基本上只用来表明客户端的能力,其中包括浏览器窗口外部的显示器的信息,如像素宽度和高度等,每个浏览器的screen对象都包含着各不相同的属性。