WebAPI
一、Web API简介1. Web APIs 和 JS 基础关联性1.1 JS 组成ECMAScript: JS 语法BOM: Web APIDOM: Web API2. API 和 Web API2.1 APIAPI:Application Programming Interface,应用程序接口。2.2 Web APIWeb API 是浏览器提供得一套操作浏览器功能和页面元素得 API(BOM
一、Web API 简介
1. Web APIs 和 JS 基础关联性
1.1 JS 组成
ECMAScript: JS 语法 BOM: Web API DOM: Web API
2. API 和 Web API
2.1 API
API:Application Programming Interface,应用程序接口。
2.2 Web API
Web API 是浏览器提供得一套操作浏览器功能和页面元素得 API(BOM 和 DOM)。
二、DOM 基础
1. DOM 简介
1.1 什么是 DOM
文档对象模型(Document Object Model,简称DOM ),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。
1.2 DOM 树
- 文档:一个页面就是一个文档,DOM中使用document表示
- 元素:页面中的所有标签都是元素,DOM中使用element表示
- 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示
以上内容都称之为对象
2. 获取元素
2.1 如何获取页面元素
DOM 在实际开发中主要用来操作元素。获取页面中的元素使用以下几种方式:
根据ID获取 根据标签名获取 通过HTML5新增的方法获取
特殊元素获取
2.2 根据 ID 获取
使用 getElementByld() 方法可以获取带有 ID 的元素对象,并返回一个 Element 对象。 console.dir() 可打印元素的属性和方法
2.3 根据标签名获取
使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。
- 返回的是 元素对象的集合,伪数组形式表示。
- 可以遍历返回的伪数组。
- 得到的元素对象是动态的。
- 若没有元素,则返回空的伪数组 []。
- 指定父元素element.getElementsByTagName(‘标签名’)
let ol = document.getElementsByTagName('ol');
console.log(ol[0].getElementsByTagName('li'));
若给 ol 指定了 id: ol ,此时得到的是带有ID的元素对象
let ol = document.getElementById('ol');
console.log(ol.getElementsByTagName('li');
2.4 通过 HTML5 新增方法获取
1、getElementsByClassName根据类名获得某些元素集合
document.getElementsByClassName('类名');
2、querySelector返回指定选择器的第一个元素盒子
document.querySelector('选择器');
3、querySelectorAll返回指定选择器的所有元素对象集合
document.querySelectorAll('选择器')
对于这些获取事件,要不就是返回一个元素对象,要不就是返回一个对象集合。对于返回的对象集合,都可以是作为一种伪数组,可以通过 elems.length 来获取元素对象个数。
2.5 获取特殊元素
1、获取 body 元素 document.body;
2、获取 html 元素 document.documentElement;
3. 事件基础
3.1 事件概述
JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。
简单理解︰触发--响应机制。
3.2 事件三要素
- 事件源:事件被触发的对象(按钮)。
- 事件类型:如何触发、什么事件(点击按钮)。
- 事件处理程序:可通过一个函数赋值的方式实现。
1、获取事件源
<button id="btn">唐伯虎</button>
2、注册事件(绑定事件)
Let btn = document.getElementById('btn');
3、添加事件处理程序(函数赋值)
btn.onclick = function() {
alert('点秋香');}
3.3 常见鼠标事件
鼠标事件 | 触发条件 |
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
4. 操作元素
使用 JavaScript DOM 可以改变网页内容、结构和样式。以下是元素的属性。
4.1 改变元素内容
element.innerText element.innerHTML
4.2 innerText(非标准) 和 innerHTML(标准) 的区别
1、innerText 不识别 html 标签,innerHTML 识别 html 标签。
div.innerHTML = ' <strong>今天是:</strong>2021-3-23';
2、innerText 会取出空格和换行,innerHTML 保留换行和空格。
4.3 常用元素的属性操作
- innerText、innerHTML 改变元素内容
- src、href
- id、alt、title
4.4 表单元素的属性操作
利用 DOM 可以操控以下表单元素的属性:
type, value, checked, selected, disabled
4.5 样式属性操作
我们可以通过JS修改元素的大小、颜色、位置等样式。
element.style:行内样式操作 element.className:类名样式操作
注意:1、Js 里面的样式采取驼峰命名法比如 fontSize、backgroundColor
2、JS修改 style 样式操作,产生的是行内样式,css 权重比较高
3、如果样式修改较多,可以采取操作类名方式更改元素样式
4、class 因为是个保留字,因此使用 className 来操作元素类名属性
5、className 会直接更改元素的类名,会覆盖原先的类名。
4.6 排他思想
如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:
1、所有元素全部清除样式(干掉其他人) 2、给当前元素设置样式(留下我自己) 3、注意顺序不能颠倒,首先干掉其他人,再设置自己。
const btns = document.getElementsByTagName('button');
for (let i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
for (let j=0;j<btns.length;j++) {
btns[j].style.backgroundColor = '';
}
this.style.backgroundColor = 'pink';
}
}
4.7 H5自定义属性
自定义属性目的:是为了保存并使用数据,有些数据可以保存到页面中而不用保存到数据库中。
H5规定自定义属性以 data- 开头作为属性名并赋值。
<div data-index="1"></div>
1、兼容性获取自定义属性 element.getAttribute('data-index')
2、H5新增element.dataset.index 或 element.dataset['index'] 获取。
3、.dataset里面存放了所有data开头的自定义属性。
4、如果自定义属性里面有多个链接的单词,则使用驼峰命名法获取。
4.8 元素属性操作
element.属性;:一般用于获取本身自带属性值。
element.getAttribute('属性');:主要获得自定义的属性(标准)我们程序员自定义的属性。
element.属性='值';:设置内置属性值。
element.setAttribute('属性', '值');:设置自定义属性。
对于 element.setAttribute 方法,若属性已存在,更新该属性值;否则,创建一个新属性。
使用 element.属性 获取或设置类名时,要用 className,而element.setAttribute() 方法,直接使用 class,即:div.setAttribute('class', 'footer')。
- element.removeAttribute(属性);
5. 结点操作
5.1为什么学节点操作
获取元素通常使用两种方式:
1、利用DOM提供的方法获取元素,缺点:逻辑性不强、繁琐
document.getElementByld()
document.getElementsByTagName()
document.querySelector()
2、利用 节点层级关系 获取元素
利用父子兄节点关系获取元素 优点:逻辑性强 缺点:兼容性稍差
5.2 节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用 node 来表示。HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
一般地,节点至少拥有 nodeType (节点类型)、nodeName (节点名称)和 nodeValue (节点值)这三个基本属性。
三种基本节点类型:
- 元素节点 nodeType 为 1 (实际开发中,主要操作的还是元素节点。)
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3(文字、空格、换行)
5.3 节点层级
获取离元素最近的父节点,若找不到则返回 null。 node.parentNode
parentNode.childNodes
返回包含指定 节点的子节点的集合,该集合为即时更新的集合。
注意:parentNode.childNodes 包含了所有的子节点,包括元素节点,文本节点等。 如果只想要获得里面的元素节点,则需要专门处理。所以我们一般不提倡使用 childNodes。
// 筛选元素节点for (let i = 0; i < ul.childNodes.length; i++) {
if (ul.childNodes[i].nodeType === 1) {
console.log(ul.childNodes[i]);
}
}
更加好的方法:获取子元素节点
parentNode.children;(非标准)
子节点方法:
① 获取 所有结点 中的第一个和最后一个:
- parentNode.firstChild
- parentNode.lastChild
② 获取 元素节点中第一个和最后一个(兼容性问题)
- parentNode.firstElementChild
- parentNode.lastElementChild
③ 实际开发(无兼容性问题)
- parentNode.children[0]
- parentNode.children[parentNode.children.length -1]
1、返回下一个兄弟节点: node.nextSibling
2、返回上一个兄弟节点: node.previousSibling
nextsibling / previousSibling 返回当前元素的下/上一个兄弟节点,找不到则返回 null。这个兄弟节点可能是是所有的节点之一(即元素节点、文本节点等)。
3、返回下一个 兄弟元素节点(≥IE9) node.nextElementSibling
4、返回上一个 兄弟元素节点(≥IE9) node.previousElementSibling
这两个方法(nextElementSibling / previousElementSibling)有兼容性问题,IE9 以上才支持。 解决方法:封装一个函数。
function getNextElementSibling(node) {
let n = node;
while (n = n.nextSibling) {
if (n.nodeType === 1) {
return n;
}
}
return null;}
document.createElement("tagName");
document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为 动态创建元素节点。在创建了元素节点后,还需要将节点添加到页面中。appendChild() 方法可以给元素节点添加子元素节点,若某元素已存在则重复添加,在页面已存在的元素 后面追加新节点。 parentNode.appendChild(childNode)
类似的,也可以使用 insertBefore() 方法在指定元素的前面插入节点。
let insertedNode = parentNode.insertBefore(newNode, referenceNode)
- insertedNode:同 newNode,待插入的新节点。
- parentNode:被插入的父节点。
- newNode:待插入的新节点。
- referenceNode:指定元素节点,新节点将插入到该元素节点的前面。
DOM 提供了 removeChild(childNode) 方法,删除一个子节点,并返回删除的节点。其中 childNode 为待删除的子节点。
// 方式一 parentNode.removeChild(childNode);
// 方式二 let oldChild = parentNode.removeChild(childNode);
node.cloneNode() 方法返回调用该方法的节点的一个副本。也称为克隆节点/拷贝节点。其中 node 为被克隆的元素节点。 node.cloneNode([deep]);
let newClone = node.cloneNode([deep]);
对于 deep 参数,可以为 true 或 false,或为空的:
deep 参数值 | 含义 |
true | 深拷贝,同时复制节点本身和里面的子节点 |
false | 浅拷贝,只复制节点本身,不复制子节点(默认) |
- document.write()
- element.innerHTML
- element.createElement()
区别:
1、document.write() 创建元素,是直接将内容写入页面的内容流,但是 当文档流执行完毕,会导致页面全部重绘。即覆盖原本的页面。
2、innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘。innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂。
3、createElement() 创建多个元素效率稍低一点点,但是结构更清晰。
总结:不同浏览器下,innerHTML 效率要比 creatElement高。
三、事件高级
1. 注册事件(绑定事件)
1.1 注册事件概述
给元素添加事件,称为注册事件或者绑定事件。
注册事件有两种方式:传统方式 和 事件监听注册方式。
1.1.1传统注册方式
- 利用on 开头的事件onclick
- 特点:注册事件的 唯一性
- 同一个元素同一个事件只能设置一个处理函数,最 后注册的处理函数将会 覆盖 前面注册的处理函数。
- w3c 标准推荐方式
- addEventListener() 它是一个方法,将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
- IE9 之前的 IE 不支持此方法,可使用 attachEvent() 代替
- 特点:同一个元素同一个事件可以注册多个监听器
- 按注册顺序依次执行
eventTarget.addEventListener(type, listener[, useCapture])
- type:事件类型字符串,比如 click 、mouseover,注意这里不要带 on。
- listener:事件处理函数,事件发生时,会调用该监听函数
- useCapture:可选参数,是一个布尔值,默认是 false。学完 DOM 事件流后,我们再进一步学习。
2. 删除事件(解绑事件)
2.1 传统注册方式
eventTarget.onclick = null;
2.2 方法监听注册方式
2.2.1 removeEventListener(≥IE9)
eventTarget.removeEventListener(type, listener[, useCapture]);
一个对象可能绑定了很多事件,对于 removeEventListener 方法,需要指定要删除的事件 listener。所以在注册事件的时候需要提前将事件函数封装在一个变量里。然后把变量传给 removeEventListener 方法。
例如:
let btns = document.querySelectorAll("button");var func1 = function () {
console.log("I \'m click(addEventListener)");
btns[0].removeEventListener("click", func1);};
btns[0].addEventListener('click', func1);
3. DOM 事件流
3.1 定义
事件流 描述的是从页面中接收事件的顺序。 事件 发生时会在元素节点之间 按照特定的顺序 传播,即 DOM 事件流。 DOM 事件流分为3个阶段:
捕获阶段 => 当前目标阶段 => 冒泡阶段
事件冒泡:IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程。
事件捕获:网景最早提出,由DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。
我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点(最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。
3.2 注意
- JS 代码中只能执行捕获或者冒泡其中的一个阶段。
- onclick 和 attachEvent 只能得到冒泡阶段。
- addEventListener(type, listener[, useCapture]) 第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是 false),表示在事件冒泡阶段调用事件处理程序。
- 实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
- 有些事件是没有冒泡的,如 onblur、onfocus、onmouseenter、onmouseleave
- 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件,我们后面讲解。
4. 事件对象
4.1 什么是事件对象
eventTarget.onclick = function(event) {}
eventTarget.addEventListener('click', function(event) {})// 这个event 就是事件对象,我们还喜欢的写成 e 或者evt
官方解释:event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
简单理解:事件发生后,跟 事件相关的一系列信息数据的集合 都放到这个事件对象event里面,它有很多属性和方法。
event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去。当我们注册事件时,event 对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)。
4.2 事件对象的常见属性和方法
事件对象属性方法 | 说明 |
e.target | 返回触发事件的对象(标准) |
e.srcElement | 返回触发事件的对象(非标准) |
e.type | 返回事件类型 |
e.preventDefault() | 阻止默认事件(标准) |
e.returnValue = true | 阻止默认事件(非标准,IE678) |
e.stopPropagation() | 阻止冒泡(标准) |
e.cancelBubble | 阻止冒泡(非标准,IE678) |
4.2.1 事件对象属性 e.target 和 this 的比较
e.target:返回的是触发事件的对象(元素),点击了哪个元素触发了事件,就返回那个元素。
this:返回的是绑定事件的对象(元素),这个事件函数的调用者。
点击了某一个元素节点,这个节点不一定绑定了事件。但是由于 DOM 事件流的冒泡现象,会触发其父节点所绑定的事件。
阻止 a 链接跳转:
标准 a.addEventListener ('click', function (e) {e.preventDefault();});
兼容IE678 a.onclick = function (e) {e.returnValue; /return false;}
5. 阻止事件冒泡
5.1 阻止事件冒泡的两种方式
事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点。
阻止事件冒泡:
标准写法:利用事件对象里面的 stopPropagation() 方法。 e.stopPropagation();
非标准写法:IE 6-8 利用事件对象 cancelBubble 属性 e.cancelBubble = true;
给相应的子元素节点设置事件的 stopPropagation() 方法,相当于在这个节点阻断了事件冒泡。事件无法继续传递至父节点。
5.2 阻止事件冒泡的兼容性解决方案
if(e && e.stopPropagation) {
e.stopPropagation();} else {
window.event.cancelBubble = true;}
6. 事件委托(代理、委派)
6.1 前言
事件冒泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握。
6.2 事件委托的原理
事件委托:也称为事件代理,在jQuery 里面称为事件委派。
原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
以上案例:给 ul 注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击 li,事件会冒泡到ul 上,ul 有注册事件,就会触发事件监听器。 作用:我们 只操作了一次 DOM ,提高了程序的性能。
7. 常用的鼠标事件
7.1 常用的鼠标事件
1、禁止鼠标右键菜单
contextmenu 主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单。
document.addEventListener('contextmenu', function(e) {
e.preventDefault();})
2、禁止鼠标选中(selectstart 开始选中)
document.addEventListener('selectstart', function(e) {
e.preventDefault();})
7.2 鼠标事件对象
event 对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象 MouseEvent 和键盘事件对象 KeyboardEvent。
鼠标事件对象 | 说明 |
e.clientX | 返回鼠标相对于浏览器窗口可视区的 X 坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的 Y 坐标 |
e.pageX | 返回鼠标相对于文档页面的 X 坐标IE9+支持 |
e.pageY | 返回鼠标相对于文档页面的 Y 坐标IE9+支持 |
e.screenX | 返回鼠标相对于电脑屏幕的 X 坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的 Y 坐标 |
8. 常用的键盘事件
8.1 常用的键盘事件
事件除了使用鼠标触发,还可以使用键盘触发。
键盘事件 | 触发事件 |
onkeyup | 某个键盘按键被松开时触发,事件不区分大小写 |
onkeydown | 某个键盘按键被按下时触发,事件不区分大小写 |
onkeypress | 某个键盘按键被按下时触发,但是不识别功能键(ctrl、shif、箭头等),区分大小写 |
onkeypress 已废弃。虽然还是有浏览器支持,但是未来可能会停止支持。请使用 keydown 代替。
8.2 键盘事件对象
键盘事件对象属性 | 说明 |
key | 返回物理按键的名称值(推荐使用) |
keyCode | 返回该键的ASCII值 |
keyCode 已废弃: 该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。一定要用,请使用 key 代替。——MDN
四、BOM 基础
1. BOM 概述
1.1 BOM 概述
BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。
BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。
BOM 缺乏标准,JavaScript 语法的标准化组织是ECMA,DOM 的标准化组织是 W3C,BOM 最初是Netscape 浏览器标准的一部分
1.2 DOM vs BOM
DOM | BOM |
文档对象模型 | 浏览器对象模型 |
DOM 就是把「文档」当做一个「对象」看待 | 把「浏览器」当做一个「对象」来看待 |
DOM 的顶级对象是 document | BOM 的顶级对象是 window |
DOM 主要学习的是操作页面元素 | BOM 学习的是浏览器窗口交互的一些对象 |
DOM 是W3C 标准规范 | BOM 是浏览器厂商在各自浏览器定义的,兼容性较差 |
1.3 BOM 的构成
BOM 比 DOM 更加强大,包含了 DOM。
window 对象是浏览器的顶级对象,它具有双重角色。
- 它是JS 访问浏览器窗口的一个接口。
- 它是一个全局对象。定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法。 在调用的时候可以省略 window,前面学习的对话框都属于 window 对象方法,如 alert()、prompt() 等。
window 下的一个特殊属性 window.name。
2. window 对象的常见事件
2.1 窗口加载事件
window.onload = function() {};
window.addEventListener("load", function(){});
window.onload 是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS文件等), 就调用的处理函数。
1、有了 window.onload 就可以把 JS 代码写到页面元素的上方,因为onload 是等页面内容全部加载完毕, 再去执行处理函数。
2、window.onload 传统注册事件方式只能写一次,如果有多个,会以最后一个 window.onload 为准。
3、如果使用 addEventListener 则没有限制。
document.addEventListener('DOMContentLoaded', function() {});
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。(Ie9以上才支持。)
如果页面的图片很多的话, 从用户访问到 onload 触发可能需要较长的时间, 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded 事件比较合适。
2.2 调整窗口大小事件
window.onresize = function(){}
window.addEventListener("resize",function(){});
window.onresize 是调整窗口大小加载事件, 当触发时就调用的处理函数。 注意:
1、只要窗口大小发生像素变化,就会触发这个事件。
2、我们经常 利用这个事件完成响应式布局。
3、window.innerWidth 是当前屏幕的宽度
3. 定时器
3.1 两种定时器
window 对象给我们提供了2 个非常好用的方法——定时器。
setTimeout() setInterval()
3.2 setTimeout() 定时器
window.setTimeout(调用函数 [, 延迟的毫秒数]);
setTimeout() 方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。
- window 可以省略。
- 这个调用函数可以 直接写函数,或者写函数名或者采取字符串 '函数名()' 三种形式。第三种不推荐。
- 延迟的毫秒数省略默认是 0,如果写,必须是毫秒。
- 因为定时器可能有很多,所以我们 经常给定时器赋值一个标识符。
setTimeout() 这个调用函数我们也称为 回调函数callback。 普通函数是按照代码顺序直接调用。而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数。
element.onclick = function(){} 或者 element.addEventListener(“click”, fn); 里面的函数也是回调函数。
3.3 停止 setTimeout() 定时器
window.clearTimeout(timeoutID)
clearTimeout() 方法用于取消先前通过调用 setTimeout() 建立的定时器。
- window 可以省略。
- 里面的 参数就是定时器的标识符。
3.4 setInterval() 定时器
window.setInterval(回调函数 [, 间隔的毫秒数]);
setInterval() 方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。
- window 可以省略。
- 这个调用函数可以 直接写函数,或者写函数名或者采取字符串'函数名()' 三种形式。
- 间隔的毫秒数省略默认是 0,如果写,必须是毫秒,表示每隔多少毫秒就自动调用这个函数。
- 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。
- 第一次执行也是间隔毫秒数之后执行,之后每隔毫秒数就执行一次,防止开始和刷新页面时的空白,可以先调用一次函数
3.5 停止 setInterval() 定时器
window.clearInterval(intervalID);
clearInterval() 方法取消了先前通过调用 setInterval() 建立的定时器。
- window 可以省略。
- 里面的参数就是定时器的标识符。
3.6 this 指向问题
this 的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定 this 到底指向谁,一般情况下的最终指向的是那个调用它的对象 现阶段,我们先了解一下几个 this 指向:
- 全局作用域或者普通函数中 this 指向全局对象 window(注意定时器里面的 this 指向 window)
- 方法调用中谁调用 this 指向谁
- 构造函数中 this 指向构造函数的实例
4. JS 执行机制
4.1 JS 是单线程
JavaScript 语言的一大特点就是 单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚 本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作DOM 而诞生的。比如我们对 某个DOM 元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是:如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
4.2 同步和异步概述
为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。于是,JS 中出现了 同步和异步。
同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。
异步:在做一件事的同时,你还可以去处理其他事情。
他们的本质区别:这条流水线上各个流程的执行顺序不同。
4.3 同步和异步任务
同步任务都在主线程上执行,形成一个 执行栈。
JS 的异步是通过回调函数实现的。 一般而言,异步任务有以下三种类型:
- 普通事件,如 click、resize 等
- 资源加载,如 load、error 等
- 定时器,包括 setInterval、setTimeout 等异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)。
4.4 JS 执行机制
- 先执行 执行栈中的同步任务。
- 异步任务(回调函数)放入任务队列中。
- 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取 任务队列 中的异步任务,于是被读取的异步务结束等待状态,进入执行栈,开始执行。
console.log(1);
document.addEventListener("click", function () {
console.log("click");});
setTimeout(function () {console.log(3);}, 3000);
console.log(2);
- 若不触发点击事件,结果将依次输出 1、2、3;
- 若点击事件在 3 秒前触发,则依次输出 1、2、click、3
- 若点击事件在 3 秒后触发,则依次输出 1、2、3、click
4.5 事件循环
由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为 事件循环(event loop)。
5. location 对象
5.1 什么是 location 对象
window 对象给我们提供了一个 location 属性用于 获取或设置窗体的URL,并且可以用于 解析 URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为 location 对象。
5.2 URL
统一资源定位符(Uniform Resource Locator, URL)是互联网上标准资源的地址。互联网上的每个文件都有 一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。 URL 的一般语法格式为:
格式 protocol://host[:port]/path/[?query]#fragment
举例 http://www.itcast.cn/index.html?name=andy&age=18#link
组成 | 说明 |
protocol | 通信协议(http、ftp) |
host | 主机(域名) |
port | 端口号(可选),省略时使用方案的默认端口,如http默认端口80 |
path | 路径,由零或多个 / 隔开的字符串,一般表示主机上的一个目录或文件地址 |
query | 参数,以键值对的形式,通过 & 符号分隔开 |
fragment | 片段,# 后面内容,常见于链接、锚点 |
5.3 location 对象的属性
location对象属性 | 返回值 |
location.href | 获取或者设置 整个URL |
location.host | 返回主机(域名) |
location.port | 返回端口号,未写则返回空字符串 |
location.pathname | 返回路径 |
location.search | 返回参数 |
location.hash | 返回片段,# 后面内容,常见于链接、锚点 |
重点记住:href 和 search
5.4 location 对象的方法
location对象方法 | 返回值 |
location.assign() | 跟 href 一样,可以跳转页面(也称为重定向页面) |
location.replace() | 替换当前页面,因为不记录历史,所以不能后退页面 |
location.reload() | 重新加载页面,相当于刷新按钿或者 f5 如果参数为 true 强制刷新 ctrl+f5 |
6. navigator 对象
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 = ""; //电脑}
7. history 对象
window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。
history对象方法 | 作用 |
back() | 网页地址后退功能 |
forward() | 前进功能 |
go(参数) | 前进后退功能,参数为 1,前进一个页面,-1 后退一个页面 |
history 对象一般在实际开发中比较少用,但是会在一些OA 办公系统中见到。
(五)PC端网页特效
1. 元素偏移量 offset 系列
1.1 offset 概述
offset 偏移量,使用 其相关属性可以动态的得到元素的位置(偏移)、大小等。
- 获得元素距离带有定位父元素的位置
- 获得元素自身的大小(宽度高度) 返回的数值都不带单位
1.2 offset 与 style 区别
offset | style |
offset 可以得到任意样式表中的样式值 | style 只能得到行内样式表中的样式值 |
offset 系列获得的数值是没有单位的 | style.width 获得的是带有单位的字符串 |
offsetWidth 包含 padding+border+width | style.width 获得不包含 padding 和 border 的值 |
offsetWidth 等属性是只读属性,只能获取不能赋值 | style.width 是可读写属性,可以获取也可以赋值 |
想要获取元素大小位置,用 offset更合适 | 想要给元素更改值,则需要用 style 改变 |
2. 元素可视区 client 系列
2.1 定义
client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
client系列属性 | 作用 |
element.clientTop | 返回元素上边框的大小 |
element.clientLeft | 返回元素左边框大大小 |
element.clientWidth | 返回自身包括 padding、内容区的宽度,不含边框,返回数值不带单位 |
element.clientHeight | 返回自身包括 padding、内容区的高度,不含边框,返回数值不带单位 |
2.2 案例:淘宝 flexible.js 源码分析
立即执行函数是指函数定义好后,不需要调用直接执行。即一引入 JS 文件,则该函数自动执行。
语法:(function() {})() 或者 (function(){}())
主要作用: 创建一个独立的作用域 避免了命名冲突问题
举例: (function () {console.log('hello');})(); // hello
可以传参数: (function (a) {console.log(a);})(10); // 10
下面三种情况都会刷新页面都会触发load 事件。
- a标签的超链接
- F5或者刷新按钮(强制刷新)
- 前进后退按钮
但是火狐中,有个特点,有个“往返缓存”,这个缓存中不仅保存着页面数据,还保存了 DOM 和 JavaScript 的状态;实际上是将整个页面都保存在了内存里。所以此时后退按钮不能刷新页面。此时可以使用 pageshow 事件来触发。这个事件在页面显示时触发,无论页面是否来自缓存。在重新加载页面中,pageshow 会在 load 事件触发后触发;根据事件对象中的 persisted 来判断是否是缓存中的页面触发的pageshow 事件,注意这个事件给 window 添加。
多个立即执行函数间要加分号 ; 隔开。
3. 元素滚动 scroll 系列
3.1 元素scroll 系列属性
scroll 滚动的,使用 scroll 相关属性可以动态的得到该元素的大小、滚动距离等。
scroll系列属性 | 作用 |
element.scrollTop | 返回被卷上去的上侧距离,返回数值不带单位 |
element.scrollLeft | 返回被卷上去的左侧距离,返回数值不带单位 |
element.scrollWidth | 返回自身实际宽度,不含边框,返回数值不带单位 |
element.scrollHeight | 返回自身实际高度,不含边框,返回数值不带单位 |
3.2 页面被卷去的头部
如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏 掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件。
获取页面被卷去的头部:
- 页面 被卷去的头部:可以通过 window.pageYOffset 获得,如果是被卷去的左侧 window.pageXOffset
- 注意,元素被卷去的头部是 element.scrollTop,左侧 element.scrollLeft
3.4 三大系列总结
三大系列大小对比 | 作用 |
element.offsetWidth | 返回自身包括 padding、边框、内容区的宽度,返回数值不带单位 |
element.clientWidth | 返回自身包括 padding、内容区宽度,不含边框,返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
- offset 系列经常用于获得元素位置 offsetLeft、offsetTop
- client 经常用于获取元素大小 clientWidth 、clientHeight
- scroll 经常用于获取滚动距离 scrollTop、scrollLeft
- 注意页面滚动的距离通过 window.pageXOffset 获得
3.5 mouseenter 和 mouseover 的区别
- 当鼠标移动到元素上时就会触发 mouseenter 事件
- mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter 只会经过自身盒子触发这样,是因为 mouseenter 不会冒泡
- 跟 mouseenter 搭配鼠标离开 mouseleave 同样不会冒泡
4. 动画函数封装
4.1 动画实现原理
核心原理:通过定时器 setInterval() 不断移动盒子位置。 实现步骤:
- 获得盒子当前位置
- 让盒子在当前位置加上 1 个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 注意此元素需要添加定位(position: absolute),才能使用 element.style.left
4.2 动画函数简单封装
注意函数需要传递 2 个参数,动画对象和移动到的距离。
function animate(obj, target) {
let timer = setInterval(function () {
if (obj.offsetLeft <= target) {
obj.style.left = obj.offsetLeft + 1 + 'px';
} else {
clearInterval(timer);
}
}, 30);}
4.3 动画函数给不同元素记录不同定时器
如果多个元素都使用这个动画函数,每次都要 var 声明定时器。我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。
核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性。
4.4 缓动效果原理
之前讲的是匀速动画:盒子当前位置 = 盒子当前位置 + 固定值
缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
- 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
- 核心算法:每次移动的距离步长 = (目标值 - 现在的位置) / 10
- 停止的条件是:让当前盒子位置等于目标位置就停止定时器
- 注意步长值需要取整
4.5 动画函数多个目标值之间移动
可以让动画函数从 800 移动到 500。
当我们点击按钮时候,判断步长是正值还是负值:
- 如果是正值,则步长往大了取整(Math.ceil())
- 如果是负值,则步长向小了取整(Math.floor())
4.6 动画函数添加回调函数
回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后, 再执行传进去的这个函数,这个过程就叫做 回调(callback)。回调函数写的位置:定时器结束的位置。
因为以后经常使用这个动画函数,可以单独封装到一个JS文件里面,使用的时候引用这个JS文件即可。
- 单独新建一个 JS 文件。
- HTML文件引入 JS 文件。
5. 常见网页特效案例
5.1 节流阀
防止轮播图按钮连续点击造成播放过快。节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。
核心思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。开始设置一个函数var flag = true; if (flag) {flag=false;do something} 关闭水龙头。利用回调函数,flag=true 打开水龙头。
5.2 返回顶部
滚动窗口至文档中的特定位置:
window.scroll(x, y) 注意:里面的 x 和 y 不跟单位,直接写数字。
- 此时可以继续使用我们封装的动画函数
- 只需要把所有的 left 相关的值改为跟页面垂直滚动距离相关就可以了
- 页面滚动了多少,可以通过 window.pageYOffset 得到
- 最后是页面滚动,使用 window.scroll(x, y)
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 缓冲动画核心算法
let step = target - window.pageYOffset;
step = step >= 0 ? Math.ceil(step / 10) : Math.floor(step / 10);
if (window.pageYOffset === target) {
clearInterval(obj.timer);
callback && callback();
}
window.scroll(0, window.pageYOffset + step);
}, 30);}
调用:
animate(window, 0);
六、本地存储
1. 本地存储概述
1.1 本地存储特性
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage 约5M、localStorage 约20M
- 只能存储字符串,可以将对象 JSON.stringify() 编码后存储
2. window.sessionStorage
2.1 特点
- 生命周期为 关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
2.2 相关操作
1、存储数据: sessionStorage.setItem(key, value)
2、获取数据: sessionStorage.getItem(key)
3、删除数据: sessionStorage.removeItem(key)
4、删除所有数据:sessionStorage.clear()
3. window.localStorage
3.1 特点
- 生命周期 永久生效,除非手动删除否则关闭页面也会存在
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
3.2 相关操作
1、存储数据: localStorage.setItem(key, value)
2、获取数据: localStorage.getItem(key)
3、删除数据: loaclStorage.removeItem(key)
4、删除所有数据:localStorage.clear()
更多推荐
所有评论(0)