一、API 和 Web API
APl ( Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
Web API是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)。
二、DOM基本操作
文档对象模型(DocumentObject Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。
2.1 DOM树
- 对于JavaScript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的dom编程接口。
- 对于HTML ,dom使得html形成一棵dom树.包含文档、元素、节点
- 文档:一个页面就是一个文档,DOM中使用document表示
- 元素:面中的所有标签都是元素,DOM中使用element表示
- 节点∶网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示
- 我们获取过来的DOM元素是一个对象( object ),所以称为文档对象模型
2.2 获取元素
2.2.1 通过ID获取
使用
getElementByld()
方法可以获取带有ID的元素对象。
<div id="time">22-8-5</div>
<script>
var timer = document.getElementById('time');
console.log(timer);
console.log(typeof timer);
console.dir(timer);
</script>
- 因为文档页面从上往下加载,所以script写在标签下面
- get 获得、element 元素、by 通过,驼峰命名法
- 参数id是大小写敏感的字符串
- 返回的是一个元素对象
console.dir()
打印返回的元素对象,可以更好的查看里面的属性和方法
2.2.2 通过标签名获取
使用
getElementsByTagName()
方法可以返回带有指定标签名的对象的集合。
以伪数组的形式组成
注意:
- 因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历
- 得到的元素对象是动态的
- 如果页面中没有这个元素,返回一个空的伪数组
还可以获取某个元素(父元素)内部所有指定标签名的子元素
elements.getElementsByTagName('标签名');
注意:
- 父元素必须是单个对象(必须指明是哪一个元素对象),获取的时候不包括父元素自己
<ol id="ol">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ol>
<script>
let ol = document.getElementById('ol');
console.log(ol.getElementsByTagName('li'));
</script>
2.2.3 H5新增获取方法
(1)根据类名返回元素对象集合
document.getElementsByClassName('类名');
(2)根据指定选择器返回第一个元素对象
document.querySelector('选择器');
(3)根据指定选择器返回
document.querySelectorAll('选择器');
2.2.4 获取特殊元素
(1)获取body元素
document.body //返回body元素对象
(2)获取html元素
document.documentElement //返回html元素对象
2.3 事件基础
JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。
网页中的每个元素都可以产生某些可以触发JavaScript的事件,例如,我可以在用户点击某按钮时产生一个事件,然后去执行某些操作。
2.3.1 事件三要素
事件是有三部分组成:事件源、事件类型、事件处理程序,我们也称为事件三要素
(1)事件源:事件被触发的对象
(2)事件类型:如何触发,什么事件。如:鼠标点击(onclick)、鼠标经过、键盘按下 等
(3)事件处理程序:通过函数赋值的方式
案例:
<div id="click">123</div>
<script>
let div = document.getElementById('click');
div.onclick = function() {
console.log('我被选中了');
}
</script>
2.3.2 常见的鼠标事件
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
补充:
- 禁用鼠标右键(
contextmenu
)
document.addEventListener('contextmenu',function(e){
e.preventDefault();
})
- 禁止鼠标选中(
selectstart
开始选中)
document.addEventListener('selectstart',function(e){
e.preventDefault();
})
- 鼠标移动事件(
mosuemove
)- 只要鼠标移动1px,就会触发这个事件
mouseenter
和mouseover
的区别- 当鼠标移动到元素上时就会触发
mouseenter
事件 - 类似
mouseover
,它们两者之间的差别是 mouseover
鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter只会经过自身盒子触发- 之所以这样,是因为
mouseenter
不会冒泡 - 跟
mouseenter
搭配,鼠标离开mouseleave
同样不会冒泡
- 当鼠标移动到元素上时就会触发
2.3.3 常用键盘事件
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键盘按键被松开时触发 |
onkeydown | 某个键盘按键被按下时触发 |
onkeypress | 某个键盘按键被按下时触发,但不识别功能键 比如 ctrl、shift、箭头等 |
注意:
- 如果使用addEventListener 不需要加 on
- 三个事件的执行顺序是:keydown – keypress – keyup
2.4 操作元素
JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。
2.4.1 改变元素内容
- 从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉
element.innerText
- 起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行
element.innerHTML
2.4.2 表单元素的属性操作
利用DOM可以操作如下表单元素的属性:
type、value、checked、selected、disabled
注意:
- 修改表单里面的内容,用
element.value = '';
- 要想禁用某个按钮,
element.disabled = true;
2.4.3 样式属性操作
element.style
行内样式操作(样式较少或功能简单的情况使用)element.className
类名样式操作(给当前元素添加类)
注意:
- JS里面的样式采取驼峰命名法,比如
fontSize
、backgroundColor
- JS修改style样式操作,产生的是行内样式,css权重比较高
className
会直接更改元素的类名,会覆盖原先的类名
2.4.4 排他思想
如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法
- 所有元素全部清除样式
- 给当前元素设置样式
- 注意顺序不能颠倒
2.4.6 自定义属性的操作
(1)获取属性值
element.属性
获取属性值element.getAttribute('属性');
区别:
element.属性
获取内置属性值(元素本身自带的属性)element.getAttribute('属性');
主要获得自定义的属性(标准) 程序员自定义的属性
(2)设置属性值
element.属性 = '值’
设置内置属性值element.setAttribute('属性','值');
(3)移除属性
element.removeAttribute('属性');
2.4.7 自定义属性
目的∶是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
(1)设置H5自定义属性
H5规定自定义属性
data-
开头作为属性名并赋值,比如:
<div data-index = "1"></div>
(2)获取H5自定义属性
- 兼容性获取:
element.getAttribute('data-index');
- H5新增
element.dataset.index
或者element.dataset['index']
(ie11才开始支持)
注意:
- dataset 是一个集合,里面存放了所有以data开头的自定义属性
- 如果自定义属性里有多个由 - 连接的单词,用第二种方法获取的时候采取驼峰命名法
2.5 节点操作
- 获取元素通常使用两种方式:
- 利用DOM提供的方式获取元素
- 利用节点层级关系获取元素:
- 利用父子兄节点关系获取元素
- 逻辑性强,但是兼容性稍差
2.5.1 节点概述
一般地,节点至少拥有nodeType(节点类型) 、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
- 元素节点 nodeType 是1
- 属性节点 nodeType 是2
- 文本节点 nodeType 是3(文本节点包含文字、空格、换行等)
2.5.2 父级节点
node.parentNode
- 得到的是离元素最近的父节点
- 如果找不到父节点则返回为null
2.5.3 子节点
(1) parentNode.childNodes
- 得到所有子节点,包含元素节点、文本节点(换行等)等等
- 如果只想要获得里面的元素节点,则需要专门处理。对nodeType进行选择
(2) parentNode.children
▲
- parentNode.children是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回
(3) parentNode.firstChild
- firstChild返回第一个子节点,找不到则返回null。同样,也是包含所有的节点
(4) parentNode.lastChild
- lastChild返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点
(5) parentNode.firstElementChild
、parentNode.lastElementChild
- 返回第一/最后一个子元素节点,找不到则返回null
2.5.4 兄弟节点
(1)node.nextSiBling
- nextsibling返回当前元素的下一个兄弟节点,找不到则返回null。同样,也是包含所有的节点
(2)node.previousSiBling
- 返回当前元素的上一个兄弟节点,找不到则返回null。同样,也是包含所有的节点
(3)node.nextElementSiBling
- nextElementsibling返回当前元素下一个兄弟元素节点,找不到测返回null
(4)node.previousElementSiBling
- 返回当前元素上一个兄弟元素节点,找不到测返回null
2.5.5 创建节点
document.createElement('tagName')
- document.createElement()方法创建由 tagName 指定的 HTML元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
2.5.6 添加节点
node.appendChild(child)
- node.appendchild()方法将一个节点添加埒指定父节点的子节点列表末尾。类似于css里面的after伪元素。
node.insertBefore(child,指定元素)
- node.insertBefore()方法将一个节点添加到父节点的指定子节点前面。类似于css里面的before伪元素。
2.5.7 删除节点
node.removeChild(child)
- node.removechild()方法从DOM中删除一个子节点,返回删除的节点。
2.5.8 复制节点(克隆节点)
node.cloneNode()
- node.cloneNode()方法返回调用该方法的节点的一个副本。也称为克隆节点/拷贝节点
注意:
- 如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
- 如果括号参数为true ,则是深拷贝,会复制节点本身以及里面所有的子节点。
2.5.9 三种动态创建元素区别
document.write()
element.innerHTML
document.creatElement()
区别:
- document.write()是直接将内容写入页面的内容流,但是当文档流执行完毕,它会导致页面全部重绘
- innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘
- innerHTML创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
- createElement()创建多个元素效率稍低一点点,但是结构更清晰
三、事件高级
3.1 注册事件
- 给元素添加事件,称为注册事件或者绑定事件
- 注册事件有两种方法:传统方式和方法监听注册方式
(1)传统注册方式
- 利用on开头的事件 onclick
<button onclick= "alert('hi~)”></button>
btn.onclick = function(){}
- 特点∶注册事件的唯一性
- 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
(2)方法监听注册方式
- w3c 标准 推荐方式
addEventListener()
是一个方法- 特点:同一个元素同一个事件可以注册多个监听器
- 按注册顺序依次执行
3.1.1 addEventListener 事件监听方式
eventTarget.addEventListener(type, listener [, useCapture])
eventTarget.addEventListener() 方法将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
该方法接收三个参数∶
- type:事件类型字符串,比如click、mouseover,注意这里不要带on,要加引号
- listener:事件处理函数,事件发生时,会调用该监听函数
- useCapture:可选参数,是一个布尔值,默认是false。
3.2 删除事件(解绑事件)
- 传统注册事件
evenTarget.onclick = null;
- 方法监听注册方式
eventTarget.removeEventListener(type, listener [, useCapture])
3.3 DOM事件流
- 事件流描述的是从页面中接收事件的顺序。
- 事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
DOM事件流分为三个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
- 事件冒泡∶IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点的过程。
- 事件捕获︰网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。
注意:
- JS代码中只能执行捕获或者冒泡其中的一个阶段
onclick
和attachEvent
只能得到冒泡阶段addEventListener(type,listener[,usecapture])
第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false (不写默认就是false ),表示在事件冒泡阶段调用事件处理程序。- 有些事件是没有冒泡的,比如:onblur、onfocus、onmouseenter、onmouseleave
3.4 事件对象
div.addEventListener('click',function(e){
console.log(e);
})
- e就是一个事件对象,写到function侦听函数的小括号里,当形参来看
- 事件对象只有有了事件才会存在,是系统自动创建的,不需要传递参数
- 事件对象是事件一系列相关数据的集合,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
- 事件对象可由我们自己命名
3.4.1 事件对象的常见属性和方法
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象 |
e.type | 返回事件的类型,比如 click、mouseover |
e.preventDefault() | 该方法阻止默认事件,比如 不让链接跳转 |
e.stopPropagation() | 阻止冒泡 |
3.4.2 鼠标事件对象
- 鼠标事件对象 MouseEvent
- 键盘事件对象 KeyboardEvent
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标 |
e.pageY | 返回鼠标相对于文档页面的Y坐标 |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
3.4.3 键盘事件对象
键盘事件对象 | 说明 |
---|---|
e.keyCode | 返回该键的ASCII值 |
e.key | 返回该键 |
注意:
- keyup和keydown 事件不区分字母大小写,如a和A得到的都是65
- keypress 事件区分大小写
案例:
let search = document.querySelector('input');
document.addEventListener('keyup',function(e){
//输出按键的ASCII码值
console.log(e.keyCode);
//按s键时光标焦点到输入框
if(e.key === 's'){
search.focus();
}
})
3.5 事件委托
原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点 ▲
案例(点击li将li背景颜色变为粉色):
let ul = document.querySelector('ul');
ul.addEventListener('chick',function(e){
e.target.style.backgroundColor = 'pink';
})