Web API 介绍
API 的概念
API(应用程序编程接口,Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,无需理解其内部工作机制细节,直接使用即可。
Web API 的概念
Web API 是浏览器提供的一套操作浏览器功能和页面元素的 API ( BOM 和 DOM )。现阶段我们主要针对于浏览器讲解常用的 API , 主要针对浏览器做交互效果。比如我们想要浏览器弹出一个警示框, 直接使用 alert(‘弹出’)。
DOM 介绍
什么是 DOM
文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(html 或者 xhtml)的标准编程接口。W3C 定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。
DOM 是 W3C 组织制定的一套处理 html 和 xml 文档的规范,所有的浏览器都遵循了这套标准。
DOM 树
DOM 树 又称为文档树模型,把文档映射成树形结构,通过节点对象对其处理,处理的结果可以加入到当前的页面。
- 文档:一个页面就是一个文档,DOM 中使用 document 表示
- 节点:网页中的所有内容,在文档树中都是节点(标签、属性、文本、注释等),使用 node 表示
- 标签节点:网页中的所有标签,通常称为元素节点,又简称为“元素”,使用 element 表示
获取元素
我们想要操作页面上的某部分(显示/隐藏,动画),需要先获取到该部分对应的元素,再对其进行操作。
根据 ID 获取
- 语法:document.getElementById(id)
- 作用:根据 ID 获取元素对象
- 参数:id 值,区分大小写的字符串
- 返回值:元素对象 或 null
案例代码
1 | <body> |
根据标签名获取元素
- 语法:document.getElementsByTagName('标签名') 或者 element.getElementsByTagName('标签名')
- 作用:根据标签名获取元素对象
- 参数:标签名
- 返回值:元素对象集合(伪数组,数组元素是元素对象)
案例代码
1 | <body> |
H5 新增获取元素方式
1. document.getElementsByClassName('类名')
2. document.querySelector('选择器') //根据指定选择器返回第一个元素对象
3. document.querySelectorAll('选择器')
querySelector
和querySelectorAll
里面的选择器需要添加符号(. | #)
案例代码
1 | <body> |
获取特殊元素
1. document.body
2. document.documentElement
1 | // 1.获取body 元素 |
事件基础
事件概述
JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个 事件,然后去执行某些操作。
事件三要素
- 事件源(谁):触发事件的元素
- 事件类型(什么事件): 例如 click 点击事件
- 事件处理程序(做啥):事件触发后要执行的代码(函数形式),事件处理函数
案例代码
1 | <body> |
执行事件的步骤
- 获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采取函数赋值方式)
案例代码
1 | <body> |
常见的鼠标事件
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键 |
onmouseover | 鼠标经过 |
onmouseout | 鼠标离开 |
onfocus | 获得鼠标焦点 |
onblur | 失去鼠标焦点 |
onmousemove | 鼠标移动 |
onmouseup | 按下鼠标按钮 |
onmousedown | 释放鼠标按钮 |
操作元素
JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内容、属性等。(注意:这些操作都是通过元素对象的属性实现的)
改变元素内容
element.innerText // 从起始位置到终止位置的内容, 但它去除 html 标签,同时空格和换行也会去掉
element.innerHTML // 起始位置到终止位置的全部内容,包括 html 标签, 同时保留空格和换行
案例代码
1 | <body> |
常用元素的属性操作
- innerText、innerHTML
- src、href
- id、alt、title
案例代码
1 | <body> |
表单元素的属性操作
利用 DOM 可以操作以下表单元素的属性:type、value、checked、selected、disabled
表单元素中有一些属性如:disabled、checked、selected,元素对象的这些属性的值是布尔型。
案例代码
1 | <body> |
显示隐藏密码
1 | <body> |
样式属性操作
- element.style 行内样式操作
- element.className 类名样式操作
注意:
- js 里面的样式采取驼峰命名法,比如:fontSize、backgroundColor
- js 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
通过操作 style 属性
1 | <body> |
显示隐藏文本框内容
1 | <body> |
通过操作 className 属性
1 | <head> |
排他思想
如果有同一组元素,我们想要某一个元素实现某种样式, 需要用到循环的排他思想算法:
- 所有元素全部清除样式(干掉其他人)
- 给当前元素设置样式 (留下我自己)
- 注意顺序不能颠倒,首先干掉其他人,再设置自己
1 | <body> |
自定义属性
获取属性值
element.属性 //获取内置属性值(元素本身自带的属性)
element.getAttribute('属性') //主要获得自定义的属性
1 | <body> |
设置属性值
element.属性 = '值'; //设置内置属性值
element.setAttribute('属性', '值'); //主要设置自定义的属性
1 | <body> |
移除属性值
element.removeAttribute('属性');
1 | // 3 移除属性 removeAttribute(属性) |
H5 自定义属性
自定义属性为了保存并使用数据, 有些数据可以保存到页面中而不用保存到数据库中。自定义属性获取是通过 DOM 元素对象 getAttribute('属性')获取。但是有些自定义属性很容易引起歧义, 不容易判断是元素的内置属性还是自定义属性,因此 H5 给我新增了自定义属性规则。
设置 H5 自定义属性
H5 规定自定义属性以data-
开头作为属性名并且赋值, 比如 <div data-index = "1"></div>
获取 H5 自定义属性
- 兼容性获取 element.getAttribute('data-index')
- H5 新增 element.dataset.index 或者 element.dataset['index']
1 | <body> |
节点操作
一般地,节点至少拥有nodeType
、nodeName
、nodeValue
这三个基本属性
- 元素节点 nodeType 为 1
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3(文本节点包含文字、空格、换行等)
父节点
node.parentNode
- parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
- 如果指定的节点没有父节点则返回 null
子节点
- parentNode.childNodes(返回值里包含了所有的子节点,包括元素节点,文本节点等)
- parentNode.children(这是一个只读属性,只返回所有的子元素节点,其余节点不返回)
- parentNode.firstChild(返回第一个子节点,找不到则返回 null,包含所有的节点)
- parent.lastChild(返回最后一个子节点,找不到则返回 null,包含所有的节点)
- parentNode.firstElementChild(返回第一个子元素节点,找不到则返回 null)
- parentNode.lastElementChild(返回最后一个子元素节点,找不到则返回 null)
实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和 lastElementChild 又有兼容性问题,因此获取第一个子元素节点和最后一个子元素节点一般用以下方法:
- 第一个子元素节点:parentNode.children[0]
- 最后一个子元素节点:parentNode.children[parentNode.children.length - 1]
兄弟节点
- node.nextSibling(返回当前元素的下一个兄弟节点,找不到则返回 null,包含所有的节点)
- node.previousSibling(返回当前元素上一个兄弟节点,找不到则返回 null,包含所有的节点)
- node.nextElementSibling(返回当前元素的下一个兄弟元素节点,找不到则返回 null
- node.previousElementSibling(返回当前元素的上一个兄弟元素节点,找不到则返回 null
创建节点
document.createElement('tagName')
因为创建的 HTML 元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点
添加节点
- node.appendChild(child) (将一个节点添加到指定父节点的子节点列表末尾)
- node.insertBefore(child, 指定元素节点) (将一个节点添加到父节点的指定子节点前面)
删除节点
node.removeChild(child)
从 DOM 中删除一个子节点,并返回删除的节点(阻止链接跳转需要添加 javascript:void(0); 或者 javascript:;)
复制节点
node.cloneNode()
返回调用该方法的节点的一个副本,也称为克隆节点/拷贝节点
注意:
- 如果括号中参数为空或者为 false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点
- 如果括号中参数为 true,则是深拷贝,会复制节点本身以及里面所有的节点
三种动态创建元素区别
- document.write()
- element.innerHTML
- document.createElement
区别:
- document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,它会导致页面重绘
- innerHTML 是将内容写入某个 DOM 节点,不会导致页面重绘
- innerHTML 创建多个元素效率更高(不拼接字符串,采取数组形式拼接)
- createElement 创建多个元素效率稍低一点点,但是结构更清晰
DOM 重点核心
关于 DOM 操作,我们针对元素的操作主要有创建、增、删、改、查、属性操作、事件操作
创建
- document.write
- innerHTML
- createElement
增
- appendChild
- insertBefore
删除
- removeChild
改
主要修改 DOM 的元素属性、内容、表单的值
- 修改元素属性:src、href、title 等
- 修改普通元素内容:innerHTML、innerText
- 修改表单元素:value、type、disabled 等
- 修改元素样式:style、className
查
- DOM 提供的 API 方法:getElementById、getElementsByTagName 古老用法。不太推荐
- H5 提供的新方法:querySelector、querySelectorAll 提倡
- 利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡
属性操作
- setAttribute:设置 DOM 的属性值
- getAttribute:得到 DOM 的属性值
- removeAttribute:移除属性
事件操作
给元素注册时间,采取 事件源.事件类型 = 事件处理程序
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键 |
onmouseover | 鼠标经过 |
onmouseout | 鼠标离开 |
onfocus | 获得鼠标焦点 |
onblur | 失去鼠标焦点 |
onmousemove | 鼠标移动 |
onmouseup | 鼠标弹起 |
onmousedown | 鼠标按下 |
注册事件
- 传统注册方式:
- 利用 on 开头的时间 onclick
- <button onclick="alert('hi')"></button>
- btn.onclick = function() {}
- 注册事件的唯一性
- 同一元素同一个事件只能设置一个函数
- 方法监听注册方式:
- W3C 标准推荐方式
- addEventListener() 它是一个方法
- IE9 之前的浏览器不支持此方法,可使用 attachEvent() 代替
- 特点:同一个元素同一个事件可以注册多个监听器
- 按注册顺序依次执行
addEventListener
eventTarget.addEventListener(type, listener{, useCapture})
该方法接收三个参数:
- type:事件类型字符串,比如 click、mouseover,注意这里不要带 on
- listener:事件处理函数,事件发生时,会调用该监听函数
- useCapture:可选参数,是一个布尔值,默认为 false
attachEvent
eventTarget.attachEvent(eventNameWithon, callback)
该方法接收两个参数:
- eventNameWithon:事件类型字符串,比如 onclick、onmouseover,这里要带 on
- callback:事件处理函数,当目标触发事件时回调函数被调用
注意:IE8 及早期版本支持
删除事件(解绑事件)
- 传统注册方式
- eventTarget.onclick = null;
- 方法监听注册方式
- eventTarget.removeEventListener(type, listener{, useCapture});
- eventTarget.detachEvent(eventNameWithon, callback);
DOM 事件流
DOM 事件流分为三个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
1 | // dom 事件流 三个阶段 |
事件对象
eventTarget.onclick = function(event) {}
eventTarget.addEventListener('click', function(event) {})
// 这个 event 就是事件对象,我们还喜欢写成 e 或者 evt
这个 event 是个形参,系统帮我们设定为事件对象,不需要传递实参进去,e.target
和this
的区别:
- this 是事件绑定的元素,这个函数的调用者(绑定这个事件的元素)
- e.target 是事件触发的元素
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象(标准) |
e.srcElement | 返回触发事件的对象(非标准 ie6-8 使用) |
e.type | 返回事件的类型,比如 click、mouseover(不带 on) |
e.returnValue | 阻止默认事件(非标准 ie6-8 使用 比如不让链接跳转) |
e.preventDefault() | 阻止默认事件(标准 比如不让链接跳转) |
e.cancelBubble | 阻止冒泡(非标准 ie6-8 使用) |
e.stopPropagation() | 阻止冒泡(标准) |
事件委托
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
1 | // 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点 |
常用的鼠标事件
- 禁止鼠标右键菜单
1 | document.addEventListener('contextmenu', function (e) { |
- 禁止鼠标选中
1 | document.addEventListener('selectstart', function (e) { |
鼠标事件对象
现阶段,我们主要是用鼠标事件对象MouseEvent
和键盘事件对象KeyboardEvent
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的 X 坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的 Y 坐标 |
e.pageX | 返回鼠标相对于文档页面的 X 坐标 IE9+ 支持 |
e.pageY | 返回鼠标相对于文档页面的 Y 坐标 IE9+ 支持 |
e.screenX | 返回鼠标相对于电脑屏幕的 X 坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的 Y 坐标 |
1 | // 计算鼠标在盒子内的坐标 |
常用的键盘事件
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键盘按键被松开时触发 |
onkeydown | 某个键盘按键被按下时触发 |
onkeypress | 某个键盘按键被按下时并弹起时触发 |
注意:onkeypress 和前面两个的区别是,它不识别功能键,比如左右箭头、shift 等
键盘事件对象
键盘事件对象 | 说明 |
---|---|
keyCode | 返回该键的 ASCII 值 |
注意:onkeydown 和 onkeyup 不区分字母大小写,onkeypress 区分字母大小写
1 | // 模拟京东按键输入内容 |