目录
Document Object Model
-
文档对象模型,通过DOM可以来任意来修改网页中各个内容
-
文档
-
文档指的是网页,一个网页就是一个文档
-
-
对象
-
对象指将网页中的每一个节点都转换为对象 转换完对象以后,就可以以一种纯面向对象的形式来操作网页了
-
-
模型
-
模型用来表示节点和节点之间的关系,方便操作页面
-
-
节点(Node)
-
节点是构成网页的最基本的单元,网页中的每一个部分都可以称为是一个节点
-
虽然都是节点,但是节点的类型却是不同的
-
常用的节点
-
文档节点 (Document),代表整个网页
-
元素节点(Element),代表网页中的标签
-
属性节点(Attribute),代表标签中的属性
-
文本节点(Text),代表网页中的文本内容
-
-
DOM操作
console.dir()可以打印我们获取的元素对象。
DOM查询
在网页中浏览器已经为我们提供了document对象, 它代表的是整个网页,它是window对象的属性,可以在页面中直接使用。
document查询方法:
-
根据元素的id属性查询一个元素节点对象:
-
document.getElementById("id属性值");
-
-
根据元素的name属性值查询一组元素节点对象:
-
document.getElementsByName("name属性值");
-
-
根据标签名来查询一组元素节点对象:
-
document.getElementsByTagName("标签名");
-
-
还可以获取某个元素(父元素)内部所有指定标签名的子元素
-
element.getElementsByTagName('标签名');
-
-
通过 HTML5 新增的方法获取
document.getElementsByClassName(‘类名’);// 根据类名返回元素对象集合
document.querySelector('选择器'); // 根据指定选择器返回第一个元素对象document.querySelectorAll('选择器'); // 根据指定选择器返回
-
获取特殊元素(body,html)
document.body // 返回body元素对象
document.documentElement // 返回html元素对象
元素的属性
-
读取元素的属性: 语法:元素.属性名 例子:ele.name ele.id ele.value ele.className
-
修改元素的属性: 语法:元素.属性名 = 属性值
-
innerHTML
-
使用该属性可以获取或设置元素内部的HTML代码
-
事件(Event)
事件三要素
1. 事件源 (谁) 2. 事件类型 (什么事件) 3. 事件处理程序 (做啥)
-
事件指的是用户和浏览器之间的交互行为。比如:点击按钮、关闭窗口、鼠标移动。。。
-
我们可以为事件来绑定回调函数来响应事件。
-
绑定事件的方式: 1.可以在标签的事件属性中设置相应的JS代码 例子:按钮 2.可以通过为对象的指定事件属性设置回调函数的形式来处理事件 例子:按钮
<script> var btn = document.getElementById("btn"); btn.onclick = function(){ }; </script>
事件源.事件类型 = 事件处理程序
文档的加载
-
浏览器在加载一个页面时,是按照自上向下的顺序加载的,加载一行执行一行。
-
如果将js代码编写到页面的上边,当代码执行时,页面中的DOM对象还没有加载, 此时将会无法正常获取到DOM对象,导致DOM操作失败。
-
解决方式一:
-
可以将js代码编写到body的下边
<body>按钮
<script> var btn = document.getElementById("btn"); btn.onclick = function(){ }; </script>
</body>
-
-
解决方式二:
-
将js代码编写到window.onload = function(){}中
-
window.onload 对应的回调函数会在整个页面加载完毕以后才执行, 所以可以确保代码执行时,DOM对象已经加载完毕了
<script> window.onload = function(){ var btn = document.getElementById("btn"); btn.onclick = function(){ }; </script>
-
改变元素内容
element.innerText 从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去掉
element.innerHTML 起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行
innerHTML 和 innerText
-
这两个属性并没有在DOM标准定义,但是大部分浏览器都支持这两个属性,两个都是可读写的
-
两个属性作用类似,都可以获取到标签内部的内容,不同是innerHTML会获取到html标签,而innerText会自动去除标签
-
如果使用这两个属性来设置标签内部的内容时,没有任何区别的,只能用于普通盒子,不能用于表单元素
src、herf、id、alt、title: element.~~ = new ~~
修改样式属性
element.style 行内样式操作
-
使用style属性来操作元素的内联样式
-
读取内联样式: 语法:元素.style.样式名
-
例子: 元素.style.width 元素.style.height
-
注意:如果样式名中带有-,则需要将样式名修改为驼峰命名法 将-去掉,然后-后的字母改大写
-
比如:background-color -->backgroundColor border-width ---> borderWidth
-
-
-
修改内联样式: 语法:元素.style.样式名 = 样式值
-
通过style修改的样式都是内联样式,由于内联样式的优先级比较高, 所以我们通过JS来修改的样式,往往会立即生效, 但是如果样式中设置了!important,则内联样式将不会生效
-
element.className 类名样式操作
-
如果样式修改较多,可以采取操作类名方式更改元素样式。
-
class因为是个保留字,因此使用className来操作元素类名属性
-
className 会直接更改元素的类名,会覆盖原先的类名。
element.className = 'oldname newname' //保留原先类名
HTML Input属性
type 属性
value属性规定输入字段的初始值,文字内容可以通过value来改变
readonly 属性规定输入字段为只读(不能修改) readonly 属性不需要值。它等同于 readonly="readonly"
disabled 属性规定输入字段是禁用(true)的。被禁用的元素是不可用和不可点击的。被禁用的元素不会被提交。 size 属性规定输入字段的尺寸(以字符计) maxlength 属性规定输入字段允许的最大长度
autocomplete 属性规定表单或输入字段是否应该自动完成。当自动完成开启,浏览器会基于用户之前的输入值自动填写值。 您可以把表单的 autocomplete 设置为 on,同时把特定的输入字段设置为 off,反之亦然。autocomplete 属性适用于 <form> 以及如下 <input> 类型:text、search、url、tel、email、password、datepickers、range 以及 color。 min 和 max 属性规定 <input> 元素的最小值和最大值。
min 和 max 属性适用于如需输入类型:number、range、date、datetime、datetime-local、month、time 以及 week。
排他思想
如果有同一组元素,我们想要某一个元素实现某种样式, 需要用到循环的排他思想算法:
-
所有元素全部清除样式(干掉其他人)
-
给当前元素设置样式 (留下我自己)
-
注意顺序不能颠倒,首先干掉其他人,再设置自己
自定义属性的操作
获取属性值
element.属性 获取属性值。
-
获取的是元素本身自带的属性
element.getAttribute('属性');
-
主要获得自定义属性(标准)【程序员自定义的属性】
设置属性值
element.属性 = 值;
-
设置内置属性值
element.setAttribute('属性','值');
-
主要设置自定义的属性(标准)
移除属性
elemeny.removeAttribute('属性');
H5自定义属性
自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。 自定义属性获取是通过getAttribute(‘属性’) 获取。 但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。 H5给我们新增了自定义属性:
-
设置H5自定义属性 H5规定自定义属性data-开头做为属性名并且赋值。 比如 <div data-index="1"></div> 或者使用 JS 设置 element.setAttribute(‘data-index’, 2)
-
获取H5自定义属性 兼容性获取 element.getAttribute(‘data-index’); H5新增 element.dataset.index 或者 element.dataset[‘index’] ie 11才开始支持
节点操作
节点概述(Node)
-
节点是构成网页的最基本的单元,网页中的每一个部分都可以称为是一个节点
-
虽然都是节点,但是节点的类型却是不同的
-
常用的节点
-
文档节点 (Document),代表整个网页
-
元素节点(Element),代表网页中的标签
-
属性节点(Attribute),代表标签中的属性
-
文本节点(Text),代表网页中的文本内容
-
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。 HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
元素节点 nodeType 为 1 属性节点 nodeType 为 2 文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等) 我们在实际开发中,节点操作主要操作的是元素节点
节点层级
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。
父级节点
node.parentNode
-
parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
-
如果指定的节点没有父节点则返回 null
子节点
-
parentNode.childNodes(标准)
parentNode.childNodes 返回包含指定节点的子节点的集合,该集合为即时更新的集合。
-
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。 如果只想要获得里面的元素节点,则需要专门处理。 所以我们一般不提倡使用childNodes
var ul = document. querySelector(‘ul’);
for(var i = 0; i < ul.childNodes.length;i++) {
if (ul.childNodes[i].nodeType == 1) {
// ul.childNodes[i] 是元素节点
console.log(ul.childNodes[i]);
}
}
-
parentNode.children(非标准)
parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回 (这个是我们重点掌握的)。
-
虽然children 是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用
-
parentNode.firstChild
firstChild 返回第一个子节点,找不到则返回null。同样,也是包含所有的节点。
-
parentNode.lastChild
lastChild 返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点。
-
parentNode.firstElementChild
firstElementChild 返回第一个子元素节点,找不到则返回null。
-
parentNode.lastElementChild
lastElementChild 返回最后一个子元素节点,找不到则返回null。
如果想要第一个子元素节点,可以使用 parentNode.chilren[0] 如果想要最后一个子元素节点,可以使用parentNode.chilren[parentNode.chilren.length - 1]
兄弟节点
-
node.nextSibling
nextSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
2. node.previousSibling
previousSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
-
node.nextElementSibling
nextElementSibling 返回当前元素下一个兄弟元素节点,找不到则返回null。
-
node.previousElementSibling
previousElementSibling 返回当前元素上一个兄弟节点,找不到则返回null。
自己封装一个兼容性的函数
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
创建节点
document.createElement('tagName')
document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
document.createTextNode() - 可以根据文本内容创建一个文本节点对象
添加节点
-
node.appendChild(child)
node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的 after 伪元素。
-
node.insertBefore(child, 指定元素)
node.insertBefore() 方法将一个节点添加到父节点的指定子节点**前面**。类似于 CSS 里面的 before 伪元素
-
node.replaceChild(新节点,旧节点)
使用一个新的节点去替换旧节点
删除节点
node.removeChild(child)
node.removeChild() 方法从 DOM 中删除一个子节点,返回删除的节点 【node是child(被删除节点)的父节点】
复制节点
node.cloneNode()
node.cloneNode() 方法返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点
1. 如果括号参数为空或者为 false ,则是浅拷 贝,即只克隆复制节点本身,不克隆里面的子 节点。 2. 如果括号参数为 true ,则是深度拷贝,会复 制节点本身以及里面所有的子节点。
三种动态创建元素区别
-
document.write()
-
element.innerHTML
-
document.createElement()
-
document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
-
innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
-
innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
-
createElement() 创建多个元素效率稍低一点点,但是结构更清晰 总结:不同浏览器下,innerHTML 效率要比 creatElement 高
事件高级
兼容性处理的原则: 首先照顾大多数浏览器,再处理特殊浏览器
addEventListener 事件监听方式
eventTarget.addEventListener(type, listener[, useCapture])
eventTarget.addEventListener()方法将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。 该方法接收三个参数:
-
type:事件类型字符串,比如 click 、mouseover ,注意这里不要带 on
-
listener:事件处理函数,事件发生时,会调用该监听函数
例如:div.addEventListener('click',fn); # fn不需要()#
-
useCapture:可选参数,是一个布尔值,默认是 false。学完 DOM 事件流后,我们再进一步学习
attachEvent 事件监听方式
(IE8及早期版本支持)
eventTarget.attachEvent(eventNameWithOn, callback)
eventTarget.attachEvent()方法将指定的监听器注册到 eventTarget(目标对象) 上,当该对象触发指定的事件时,指定的回调函数就会被执行。 该方法接收两个参数:
-
eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
-
callback: 事件处理函数,当目标触发事件时回调函数被调用 注意:IE8 及早期版本支持
兼容性处理的原则: 首先照顾大多数浏览器,再处理特殊浏览器
function addEventListener(element, eventName, fn) {
// 判断当前浏览器是否支持 addEventListener 方法
if (element.addEventListener) {
element.addEventListener(eventName, fn); // 第三个参数 默认是false
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, fn);
} else {
// 相当于 element.onclick = fn;
element['on' + eventName] = fn;
}
删除事件的方式
删除事件兼容性解决方案
function removeEventListener(element, eventName, fn) {
// 判断当前浏览器是否支持 removeEventListener 方法
if (element.removeEventListener) {
element.removeEventListener(eventName, fn); // 第三个参数 默认是false
} else if (element.detachEvent) {
element.detachEvent('on' + eventName, fn);
} else {
element['on' + eventName] = null;
}
DOM 事件流
事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流。
注意
-
JS 代码中只能执行捕获或者冒泡其中的一个阶段。
-
onclick 和 attachEvent 只能得到冒泡阶段。
-
addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
-
实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
-
有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
-
事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件,我们后面讲解。
事件对象
eventTarget.onclick = function(event) {} eventTarget.addEventListener('click', function(event) {}) // 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
官方解释:event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。 简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象 event,它有很多属性和方法。 比如:
-
谁绑定了这个事件。
-
鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。
-
键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
这个 event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去。 当我们注册事件时, event 对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)。
事件对象本身的获取存在兼容问题:
-
标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。
-
在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找。 解决: e = e || window.event;
e.target 和 this 的区别:
-
this 是事件绑定的元素, 这个函数的调用者(返回绑定这个事件的元素)
-
e.target 是事件触发的元素 点击哪个返回哪个
阻止事件冒泡
标准写法:利用事件对象里面的 stopPropagation()方法
e.stopPropagation()
非标准写法:IE 6-8 利用事件对象 cancelBubble 属性
e.cancelBubble = true;
阻止事件冒泡的兼容性解决方案
if(e && e.stopPropagation){ e.stopPropagation(); }else{ window.event.cancelBubble = true; }
事件委托
事件委托也称为事件代理, 在 jQuery 里面称为事件委派
事件委托的原理 不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。使用e.target
作用:我们只操作了一次 DOM ,提高了程序的性能。
常用的鼠标事件
常用的鼠标事件
1.禁止鼠标右键菜单 contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
2.禁止鼠标选中(selectstart 开始选中)
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
鼠标事件对象
event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象 MouseEvent 和键盘事件对象 KeyboardEvent。
常用的键盘事件
常用的键盘事件
事件除了使用鼠标触发,还可以使用键盘触发
注意:
-
如果使用addEventListener 不需要加 on
-
onkeypress 和前面2个的区别是,它不识别功能键,比如左右箭头,shift 等。
-
三个事件的执行顺序是: keydown -- keypress --- keyup
键盘事件对象
注意: onkeydown 和 onkeyup 不区分字母大小写,onkeypress 区分字母大小写。 在我们实际开发中,我们更多的使用keydown和keyup, 它能识别所有的键(包括功能键) Keypress 不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值
DOM对CSS的操作
-
读取元素的当前样式
-
正常浏览器
-
使用getComputedStyle()
-
这个方法是window对象的方法,可以返回一个对象,这个对象中保存着当前元素生效样式
-
参数: 1.要获取样式的元素 2.可以传递一个伪元素,一般传null
-
例子: 获取元素的宽度 getComputedStyle(box , null)["width"];
-
通过该方法读取到样式都是只读的不能修改
-
-
IE8
-
使用currentStyle
-
语法: 元素.currentStyle.样式名
-
例子: box.currentStyle["width"]
-
通过这个属性读取到的样式是只读的不能修改
-
-
-
其他的样式相关的属性 注意:以下样式都是只读的
clientHeight - 元素的可见高度,指元素的内容区和内边距的高度 clientWidth - 元素的可见宽度,指元素的内容区和内边距的宽度 offsetHeight - 整个元素的高度,包括内容区、内边距、边框 offfsetWidth - 整个元素的宽度,包括内容区、内边距、边框 offsetParent - 当前元素的定位父元素 - 离他最近的开启了定位的祖先元素,如果所有的元素都没有开启定位,则返回body offsetLeft offsetTop - 当前元素和定位父元素之间的偏移量 - offsetLeft水平偏移量 offsetTop垂直偏移量
scrollHeight scrollWidth - 获取元素滚动区域的高度和宽度
scrollTop scrollLeft - 获取元素垂直和水平滚动条滚动的距离
判断滚动条是否滚动到底 - 垂直滚动条 scrollHeight - scrollTop = clientHeight
-
水平滚动 scrollWidth - scrollLeft = clientWidth
-