JavaScript+Web APIs
一、JavaScript
1、JavaScript 是什么
- JavaScript 是世界上最流行的语言之一,是一种运行在客户端的脚本语言 (Script 是脚本的意思)
- 脚本语言:不需要编译,运行过程中由 js 解释器( js 引擎)逐行来进行解释并执行
- 现在也可以基于 Node.js 技术进行服务器端编程
2、JavaScript的作用
- 表单动态校验(密码强度检测) ( JS 产生最初的目的 )
- 网页特效
- 服务端开发(Node.js)
- 桌面程序(Electron)
- App(Cordova)
- 控制硬件-物联网(Ruff)
- 游戏开发(cocos2d-js)
3 、浏览器执行 JS 简介
浏览器分成两部分:渲染引擎和 JS 引擎
浏览器本身并不会执行JS代码,而是通过内置 JavaScript 引擎(解释器) 来执行 JS 代码 。JS 引擎执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以 JavaScript 语言归为脚本语言,会逐行解释执行。
4、JS 的组成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E7y89qfh-1638882471111)(G:/html笔记/07-10 JavaScript网页编程/01-JavaScript基础语法资料/JavaScript基础第01天/4-笔记/images/图片11.png)]
5 、JavaScript输入输出语句
为了方便信息的输入输出,JS中提供了一些输入输出语句,其常用的语句如下:
方法 | 说明 | 归属 |
---|---|---|
alert(msg) | 浏览器弹出警示框 | 浏览器 |
console.log(msg) | 浏览器控制台打印输出信息 | 浏览器 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
- 注意:alert() 主要用来显示消息给用户,console.log() 用来给程序员自己看运行时的消息。
6、预解析的相关概念
JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。
-
预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义。
-
代码执行: 从上到下执行JS语句。
预解析会把变量和函数的声明在代码执行之前执行完成。
变量预解析
预解析也叫做变量、函数提升。
变量提升(变量预解析): 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升。
console.log(num); // 结果是多少?
var num = 10; // ?
结果:undefined
注意:**变量提升只提升声明,不提升赋值**
函数预解析
函数提升: 函数的声明会被提升到当前作用域的最上面,但是不会调用函数。
fn();
function fn() {
console.log('打印');
}
结果:控制台打印字符串 --- ”打印“
注意:函数声明代表函数整体,所以函数提升后,函数名代表整个函数,但是函数并没有被调用!
函数表达式声明函数问题
函数表达式创建函数,会执行变量提升,此时接收函数的变量名无法正确的调用:
fn();
var fn = function() {
console.log('想不到吧');
}
结果:报错提示 ”fn is not a function"
解释:该段代码执行之前,会做变量声明提升,fn在提升之后的值是undefined;而fn调用是在fn被赋值为函数体之前,此时fn的值是undefined,所以无法正确调用
二、 对象
2.1创建对象的三种方式
1.利用字面量创建对象
使用对象字面量创建对象:就是花括号 { } 里面包含了表达这个具体事物(对象)的属性和方法;{ } 里面采取键值对的形式表示
2.利用 new Object 创建对象
- 创建空对象
var andy = new Obect(); 通过内置构造函数Object创建对象,此时andy变量已经保存了创建出来的空对象
3.利用构造函数创建对象
构造函数
-
构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
-
构造函数的封装格式:
function 构造函数名(形参1,形参2,形参3) {
this.属性名1 = 参数1;
this.属性名2 = 参数2;
this.属性名3 = 参数3;
this.方法名 = 函数体;
}
构造函数的调用格式
var obj = new 构造函数名(实参1,实参2,实参3)
注意事项
- 构造函数约定首字母大写。
- 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
- 构造函数中不需要 return 返回结果。
- 当我们创建对象的时候,必须用 new 来调用构造函数。
new***关键字的作用***
- 在构造函数代码开始执行之前,创建一个空对象;
- 修改this的指向,把this指向创建出来的空对象;
- 执行函数的代码
- 在函数完成之后,返回this—即创建出来的对象
三、内置对象
JavaScript 中的对象分为3种:自定义对象 、内置对象、 浏览器对象
前面两种对象是JS 基础 内容,属于 ECMAScript; 第三个浏览器对象属于 JS 独有的
1.Math对象
Math 对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用 Math 中的成员。
属性、方法名 | 功能 |
---|---|
Math.PI | 圆周率 |
Math.floor() | 向下取整 |
Math.ceil() | 向上取整 |
Math.round() | 四舍五入版 就近取整 注意 -3.5 结果是 -3 |
Math.abs() | 绝对值 |
Math.max()/Math.min() | 求最大和最小值 |
Math.random() | 获取范围在[0,1)内的随机值 |
注意:上面的方法使用时必须带括号
获取指定范围内的随机整数:
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
2 日期对象
Date 对象和 Math 对象不一样,Date是一个构造函数,所以使用时需要实例化后才能使用其中具体方法和属性。Date 实例用来处理日期和时间
-
使用Date实例化日期对象
- 获取当前时间必须实例化:
var now = new Date();
- 获取指定时间的日期对象
var future = new Date('2019/5/1');
注意:如果创建实例时并未传入参数,则得到的日期对象是当前时间对应的日期对象
-
使用Date实例的方法和属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5unLTjjL-1638882471113)(G:/html笔记/07-10 JavaScript网页编程/01-JavaScript基础语法资料/JavaScript基础第06天/4-笔记/images/图片1.png)]
-
通过Date实例获取总毫秒数
-
总毫秒数的含义
基于1970年1月1日(世界标准时间)起的毫秒数
-
获取总毫秒数
// 实例化Date对象 var now = new Date(); // 1. 用于获取对象的原始值 console.log(date.valueOf()) console.log(date.getTime()) // 2. 简单写可以这么做 var now = + new Date(); // 3. HTML5中提供的方法,有兼容性问题 var now = Date.now();
-
3 数组对象
创建数组的两种方式
-
字面量方式
-
示例代码如下:
var arr = [1,"test",true];
-
-
new Array()
-
示例代码如下:
var arr = new Array();
注意:上面代码中arr创建出的是一个空数组,如果需要使用构造函数Array创建非空数组,可以在创建数组时传入参数
参数传递规则如下:
-
如果只传入一个参数,则参数规定了数组的长度
-
如果传入了多个参数,则参数称为数组的元素
-
-
检测是否为数组
instanceof 可以判断一个对象是否是某个构造函数的实例
4 添加删除数组元素的方法
-
数组中有进行增加、删除元素的方法,部分方法如下表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nwnz1TUL-1638882471114)(G:/html笔记/07-10 JavaScript网页编程/01-JavaScript基础语法资料/JavaScript基础第06天/4-笔记/images/图片2.png)]
注意:push、unshift为增加元素方法;pop、shift为删除元素的方法
5 数组排序
-
数组中有对数组本身排序的方法,部分方法如下表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1oTKksF8-1638882471115)(G:/html笔记/07-10 JavaScript网页编程/01-JavaScript基础语法资料/JavaScript基础第06天/4-笔记/images/图片3.png)]
注意:sort方法需要传入参数来设置升序、降序排序
- 如果传入“function(a,b){ return a-b;}”,则为升序
- 如果传入“function(a,b){ return b-a;}”,则为降序
6 数组索引方法
-
数组中有获取数组指定元素索引值的方法,部分方法如下表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bQCdOqYy-1638882471120)(G:/html笔记/07-10 JavaScript网页编程/01-JavaScript基础语法资料/JavaScript基础第06天/4-笔记/images/图片4.png)]
7 数组转换为字符串
-
数组中有把数组转化为字符串的方法,部分方法如下表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dy4vTIkF-1638882471121)(G:/html笔记/07-10 JavaScript网页编程/01-JavaScript基础语法资料/JavaScript基础第06天/4-笔记/images/图片5.png)]
注意:join方法如果不传入参数,则按照 “ , ”拼接元素
8 其他方法
-
数组中还有其他操作方法,同学们可以在课下自行查阅学习
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yDUruOiP-1638882471122)(G:/html笔记/07-10 JavaScript网页编程/01-JavaScript基础语法资料/JavaScript基础第06天/4-笔记/images/图片6.png)]
9 根据位置返回字符
字符串通过基本包装类型可以调用部分方法来操作字符串,以下是根据位置返回指定位置上的字符:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mjTBe1VG-1638882471123)(G:/html笔记/07-10 JavaScript网页编程/01-JavaScript基础语法资料/JavaScript基础第06天/4-笔记/images/图片8.png)]
10 字符串操作方法
字符串通过基本包装类型可以调用部分方法来操作字符串,以下是部分操作方法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eUJygRec-1638882471124)(G:/html笔记/07-10 JavaScript网页编程/01-JavaScript基础语法资料/JavaScript基础第06天/4-笔记/images/图片10.png)]
11 replace()方法
replace() 方法用于在字符串中用一些字符替换另一些字符,其使用格式如下:
字符串.replace(被替换的字符串, 要替换为的字符串);
12 split()方法
split()方法用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。
其使用格式如下:
字符串.split("分割字符")
四、Web APIs
1.Web APIs 阶段
Web APIs 是 W3C 组织的标准
Web APIs 我们主要学习 DOM 和 BOM
Web APIs 是我们 JS 所独有的部分
我们主要学习页面交互功能
需要使用 JS 基础的课程内容做基础
JS 基础学习 ECMAScript 基础语法为后面作铺垫, Web APIs 是 JS 的应用,大量使用 JS 基础语法做交互效果*
Web API 是浏览器提供的一套操作浏览器功能和页面元素的 API ( BOM 和 DOM )。
Web API 一般都有输入和输出(函数的传参和返回值),Web API 很多都是方法(函数)
什么是 DOM
文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
3.如何获取页面元素
3.1根据 ID 获取
使用 getElementById() 方法可以获取带有 ID 的元素对象。 document.getElementById(‘id’);
用 console.dir() 可以打印我们获取的元素对象,更好的查看对象里面的属性和方法。
3.2根据标签名获取
1.使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。 document.getElementsByTagName(‘标签名’);
注意:
因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历。
得到元素对象是动态的
如果获取不到元素,则返回为空的伪数组(因为获取不到对象)
2.可以获取某个元素(父元素)内部所有指定标签名的子元素. element.getElementsByTagName(‘标签名’);
注意:父元素必须是单个对象(必须指明是哪一个元素对象). 获取的时候不包括父元素自己。
3.3通过 HTML5 新增的方法获取
-
document.getElementsByClassName(‘类名’);// 根据类名返回元素对象集合
-
document.querySelector(‘选择器’); // 根据指定选择器返回第一个元素对象
-
document.querySelectorAll(‘选择器’); // 根据指定选择器返回
注意:
querySelector 和 querySelectorAll里面的选择器需要加符号,比如:document.querySelector(’#nav’);
3.4特殊元素获取
- doucumnet.body // 返回body元素对象
- document.documentElement // 返回html元素对象
4.事件基础
JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。
简单理解: 触发— 响应机制。
网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个 事件,然后去执行某些操作
4.1 事件三要素
- 事件源 (谁) 获取事件源(按钮)
- 事件类型 (什么事件)注册事件(绑定事件),使用 onclick
- 事件处理程序 (做啥)编写事件处理程序,写一个函数弹出 alert 警示框
4.2 执行事件的步骤
1. 获取事件源
2. 注册事件(绑定事件)
3. 添加事件处理程序(采取函数赋值形式)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VkqPysFV-1638882471125)(C:\Users\Wang\AppData\Roaming\Typora\typora-user-images\image-20210721122452730.png)]
5.操作元素
JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内容 、属性等。注意以下都是属性
5.1 改变元素内容
element.innerText 从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去掉
element.innerHTML 起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行
5.2 常用元素的属性操作
-
innerText、innerHTML 改变元素内容
-
src、href
-
id、alt、title
5.3 表单元素的属性操作
利用 DOM 可以操作如下表单元素的属性:
type、value、checked、selected、disabled
5.4 样式属性操作
样式属性操作
-
element.style 行内样式操作
-
element.className 类名样式操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yimev4Bh-1638882471127)(C:\Users\Wang\AppData\Roaming\Typora\typora-user-images\image-20210721123124181.png)]
注意:
- 如果样式修改较多,可以采取操作类名方式更改元素样式。
- class因为是个保留字,因此使用className来操作元素类名属性
3.className 会直接更改元素的类名,会覆盖原先的类名。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rZstd2qX-1638882471129)(C:\Users\Wang\AppData\Roaming\Typora\typora-user-images\image-20210721123341056.png)]
5.5 自定义属性的操作
1.设置属性值
element.属性 = ‘值’ 设置内置属性值。
element.setAttribute(‘属性’, ‘值’);
-
区 别:
element.属性 设置内置属性值
element.setAttribute(‘属性’); 主要设置自定义的属性 (标准) -
移除属性
element.removeAttribute(‘属性’);
5.6 H5自定义属性
自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
自定义属性获取是通过getAttribute(‘属性’) 获取。
但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。
H5给我们新增了自定义属性:
-
设置H5自定义属性
H5规定自定义属性data-开头做为属性名并且赋值。
比如
或者使用 JS 设置
element.setAttribute(‘data-index’, 2) -
获取H5自定义属性
兼容性获取 element.getAttribute(‘data-index’);
H5新增 element.dataset.index 或者 element.dataset[‘index’] ie 11才开始支持
6.节点操作
6.1获取元素通常使用两种方式:
- 利用 DOM 提供的方法获取元素
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eFrV4TaY-1638882471130)(C:\Users\Wang\AppData\Roaming\Typora\typora-user-images\image-20210721123944300.png)]
-
利用节点层级关系获取元素
利用父子兄节点关系获取元素
逻辑性强, 但是兼容性稍差
6.2 节点概述
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
元素节点 nodeType 为 1
属性节点 nodeType 为 2
文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)
我们在实际开发中,节点操作主要操作的是元素节点
6.3 节点层级
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。
1. 父级节点
node.parentNode
parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
如果指定的节点没有父节点则返回 null
2. 子节点
-
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]);}
}
2. parentNode.children(非标准)
parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回 (这个是我们重点掌握的)。虽然children 是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用
3. parentNode.firstChild
firstChild 返回第一个子节点,找不到则返回null。同样,也是包含所有的节点。
4. parentNode.lastChild
lastChild 返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点。
5. parentNode.firstElementChild IE9 以上才支持。
firstElementChild 返回第一个子元素节点,找不到则返回null。
6. parentNode.lastElementChild ** IE9 以上才支持。*
lastElementChild 返回最后一个子元素节点,找不到则返回null。
实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和 lastElementChild 又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?
解决方案:
如果想要第一个子元素节点,可以使用 parentNode.chilren[0]
***如果想要最后一个子元素节点,可以使用 parentNode.chilren[parentNode.chilren.length - 1] *****
3.兄弟节点
-
node.nextSibling nextSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
-
node.previousSibling previousSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
-
node.nextElementSibling**(IE9 以上才支持)** nextElementSibling 返回当前元素下一个兄弟元素节点,找不到则返回null。
-
node.previousElementSibling**(IE9 以上才支持)** previousElementSibling 返回当前元素上一个兄弟节点,找不到则返回null。
兄弟节点 解决兼容问题
自己封装一个兼容性的函数
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
6.4 创建节点
document.createElement(‘tagName’)
document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
1.添加节点
-
node.appendChild(child)
node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的 after 伪元素。
-
node.insertBefore(child, 指定元素)
node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素。
2.删除节点
node.removeChild(child)
node.removeChild() 方法从 DOM 中删除一个子节点,返回删除的节点。
3.复制节点(克隆节点)
node.cloneNode()
node.cloneNode() 方法返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点
注意:
-
如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
-
如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点。
4.三种动态创建元素区别
document.write()
element.innerHTML
document.createElement()
区别:
- document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
- innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
- innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
- createElement() 创建多个元素效率稍低一点点,但是结构更清晰
总结:不同浏览器下,innerHTML 效率要比 creatElement 高
五、 事件高级
(一)注册事件
1.注册事件概述
给元素添加事件,称为注册事件或者绑定事件。
注册事件有两种方式:传统方式和* 方法监听注册方式**
传统注册方式
利用 on 开头的事件 onclick
<button οnclick=“alert(‘hi~’)”>
btn.onclick = function() {}
特点: 注册事件的唯一性
同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
方法监听注册方式
w3c 标准 推荐方式
addEventListener() 它是一个方法
IE9 之前的 IE 不支持此方法,可使用 attachEvent() 代替
特点:同一个元素同一个事件可以注册多个监听器
按注册顺序依次执行
2.addEventListener 事件监听方式
eventTarget.addEventListener(type, listener[, useCapture])
eventTarget.addEventListener()方法将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
该方法接收三个参数:
type:事件类型字符串,比如 click 、mouseover ,注意这里不要带 on
listener:事件处理函数,事件发生时,会调用该监听函数
useCapture:可选参数,是一个布尔值,默认是 false。
3.attachEvent 事件监听方式
eventTarget.attachEvent(eventNameWithOn, callback)
eventTarget.attachEvent()方法将指定的监听器注册到 eventTarget(目标对象) 上,当该对象触发指定的事件时,指定的回调函数就会被执行。
该方法接收两个参数:
eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
callback: 事件处理函数,当目标触发事件时回调函数被调用
注意:IE8 及早期版本支持
4.注册事件兼容性解决方案
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;
}
兼容性处理的原则: 首先照顾大多数浏览器,再处理特殊浏览器
(二)删除事件
1.删除事件的方式
1.1传统注册方式
eventTarget.onclick = null;
1.2方法监听注册方式
1.eventTarget.removeEventListener(type, listener[, useCapture]);
2.eventTarget.detachEvent(eventNameWithOn, callback);
2.删除事件兼容性解决方案
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 事件流。
DOM 事件流分为3个阶段:
-
捕获阶段
-
当前目标阶段
-
冒泡阶段
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A1KEWRdB-1638882471131)(assets\图片2.png)]
事件冒泡: IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程。
事件捕获: 网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ajpcvJVh-1638882471132)(C:\Users\Wang\AppData\Roaming\Typora\typora-user-images\image-20210722112240371.png)]
注意
1.JS 代码中只能执行捕获或者冒泡其中的一个阶段。
2.onclick 和 attachEvent 只能得到冒泡阶段。
3.addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
4.实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
5.有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
(四)事件对象
4.1 什么是事件对象
官方解释:event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象 event,它有很多属性和方法
4.2 事件对象的使用语法
eventTarget.onclick = function(event) {}
eventTarget.addEventListener(‘click’, function(event) {})
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
//这个 event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去。
//当我们注册事件时, event 对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)。
4.3 事件对象的兼容性方案
件对象本身的获取存在兼容问题:
- 标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。
- 在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找。
解决: e = e || window.event;
4.4 事件对象的常见属性和方法
e.target 和 this 的区别:
this 是事件绑定的元素, 这个函数的调用者(绑定这个事件的元素)
e.target 是事件触发的元素。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-216EhL0p-1638882471132)(C:\Users\Wang\AppData\Roaming\Typora\typora-user-images\image-20210722113057024.png)]
(五)阻止事件冒泡
5.1 阻止事件冒泡的两种方式
事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点。事件冒泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握。
阻止事件冒泡
***标准写法:***利用事件对象里面的 stopPropagation()方法 e.stopPropagation()
非标准写法:IE 6-8 利用事件对象 cancelBubble 属性 e.cancelBubble = true;
5.2 阻止事件冒泡的兼容性解决方案
if(e && e.stopPropagation){
e.stopPropagation();
}else{
window.event.cancelBubble = true;
}
(六)事件委托的原理
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
**作用:只操作了一次 DOM ,提高了程序的性能。
(七)常用的鼠标事件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZzAy7XOk-1638882471133)(C:\Users\Wang\AppData\Roaming\Typora\typora-user-images\image-20210722114107654.png)]
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。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sHUbYg80-1638882471134)(C:\Users\Wang\AppData\Roaming\Typora\typora-user-images\image-20210722114311814.png)]
BOM
一、什么是 BOM
BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。
BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。
BOM 缺乏标准,JavaScript 语法的标准化组织是 ECMA,DOM 的标准化组织是 W3C,BOM 最初是Netscape 浏览器标准的一部分。
1.Dom与Bom对比
文档对象模型
DOM 就是把「文档」当做一个「对象」来看待
DOM 的顶级对象是 document
DOM 主要学习的是操作页面元素
DOM 是 W3C 标准规范
Bom:***
浏览器对象模型
把「浏览器」当做一个「对象」来看待
BOM 的顶级对象是 window
BOM 学习的是浏览器窗口交互的一些对象
BOM 是浏览器厂商在各自浏览器上定义的,兼容性较差
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g8J9bOXn-1638882471136)(C:\Users\Wang\AppData\Roaming\Typora\typora-user-images\image-20210722120751164.png)]
2.Bom的组成
window 对象是浏览器的顶级对象,它具有双重角色。
它是 JS 访问浏览器窗口的一个接口。
它是一个全局对象。定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法。
在调用的时候可以省略 window,前面学习的对话框都属于 window 对象方法,如 alert()、prompt() 等。注意:window下的一个特殊属性 window.name
二、window 对象的常见事件
2.1 窗口加载事件
2.1.1
window.onload = function(){} 或者 window.addEventListener(“load”,function(){});
window.onload 是窗口 (页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等), 就调用的处理函数。
注意:
-
有了 window.onload 就可以把 JS 代码写到页面元素的上方,因为 onload 是等页面内容全部加载完毕,再去执行处理函数。
-
window.onload 传统注册事件方式 只能写一次,如果有多个,会以最后一个 window.onload 为准。
-
如果使用 addEventListener 则没有限制
2.1.2
document.addEventListener(‘DOMContentLoaded’,function(){})
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。Ie9以上才支持
如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded 事件比较合适。
2.2 调整窗口大小事件
window.onresize = function(){}
window.addEventListener(“resize”,function(){});
window.onresize 是调整窗口大小加载事件, 当触发时就调用的处理函数。
注意:
-
只要窗口大小发生像素变化,就会触发这个事件。
-
我们经常利用这个事件完成响应式布局。 window.innerWidth 当前屏幕的宽度
三、定时器
3.1两种定时器
window 对象给我们提供了 2 个非常好用的方法-定时器。
setTimeout()
setInterval()
3.2 setTimeout() 定时器
window.setTimeout(调用函数, [延迟的毫秒数]);
setTimeout() 方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。
注意:
-
window 可以省略。
-
这个调用函数可以直接写函数,或者写函数名或者采取字符串‘函数名()'三种形式。第三种不推荐
-
延迟的毫秒数省略默认是 0,如果写,必须是毫秒。
-
因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。
setTimeout() 这个调用函数我们也称为回调函数 callback
普通函数是按照代码顺序直接调用。
而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数。
3.3 停止 setTimeout() 定时器
window.clearTimeout(timeoutID) clearTimeout()方法取消了先前通过调用 setTimeout() 建立的定时器。
3.4 setInterval() 定时器
window.setInterval(回调函数, [间隔的毫秒数]);
setInterval() 方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。
注意:
-
window 可以省略。
-
这个调用函数可以直接写函数,或者写函数名或者采取字符串 ‘函数名()’ 三种形式。
-
间隔的毫秒数省略默认是 0,如果写,必须是毫秒,表示每隔多少毫秒就自动调用这个函数。
4.因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。 -
第一次执行也是间隔毫秒数之后执行,之后每隔毫秒数就执行一次。
3.5 停止 setInterval() 定时器
window.clearInterval(intervalID); clearInterval()方法取消了先前通过调用 setInterval()建立的定时器。
3.6 this
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,一般情况下this的最终指向的是那个调用它的对象
现阶段,我们先了解一下几个this指向
- 全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)
- 方法调用中谁调用this指向谁
3.构造函数中this指向构造函数的实例
四、JS的执行机制
4.1 JS 是单线程
JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
4.2 同步和异步
为了解决 JS 执行的时间过长,造成页面的渲染不连贯,导致页面渲染加载阻塞。利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。于是,JS 中出现了同步和异步。
**同步:**前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。
**异步:**做这件事的同时,你还可以去处理其他事情
本质区别: 这条流水线上各个流程的执行顺序不同。
4.3同步任务和异步任务
同步任务都在主线程上执行,形成一个执行栈。
JS 的异步是通过回调函数实现的。
一般而言,异步任务有以下三种类型:
1、普通事件,如 click、resize 等
2、资源加载,如 load、error 等
3、定时器,包括 setInterval、setTimeout 等
异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)。
4.4 JS 执行机制
-
先执行执行栈中的同步任务。
-
异步任务(回调函数)放入任务队列中。
-
一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pttSwnhV-1638882471137)(assets\图片1.png)]
五、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
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HPYQrJlW-1638882471138)(assets\图片3.png)]
5.3 location 对象的属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dp3Ay1dy-1638882471139)(assets\图片4.png)]
**重点记住: href 和 search
六、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 = “”; //电脑
}
七、history 对象
window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的 URL。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PZJPRuQ9-1638882471139)(assets\图片5.png)]
PC端网页特效
一、元素偏移量offset系列
1.1 offset 概述
offset 翻译过来就是偏移量, 我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
获得元素距离带有定位父元素的位置
获得元素自身的大小(宽度高度)
注意: 返回的数值都不带单位
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tANIMm5r-1638882471140)(assets\图片6.png)]
1.2 offset 与 style 区别
offset
offset 可以得到任意样式表中的样式值
offset 系列获得的数值是没有单位的
offsetWidth 包含padding+border+width
offsetWidth 等属性是只读属性,只能获取不能赋值
所以,我们想要获取元素大小位置,用offset更合适
style
style 只能得到行内样式表中的样式值
style.width 获得的是带有单位的字符串
style.width 获得不包含padding和border 的值
style.width 是可读写属性,可以获取也可以赋值
所以,我们想要给元素更改值,则需要用style改变
二、元素可视区 client 系列
client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过 client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W8Rj58Wf-1638882471141)(assets\图片7.png)]
三、 元素滚动 scroll 系列
3.1 元素 scroll 系列属性
scroll 翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Leaqp4F0-1638882471142)(assets\1.png)]
3.1 元素 scroll 系列属性
如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件。
三大系列总结
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wQasZZCh-1638882471144)(assets\2.png)]
他们主要用法:
offset系列 经常用于获得元素位置 offsetLeft offsetTop
client 经常用于获取元素大小 clientWidth clientHeight
scroll 经常用于获取滚动距离 scrollTop scrollLeft
注意页面滚动的距离通过 window.pageXOffset 获得
四、mouseenter 和mouseover的区别
4.1mouseenter 鼠标事件
当鼠标移动到元素上时就会触发 mouseenter 事件,类似 mouseover,它们两者之间的差别是: mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。 mouseenter 只会经过自身盒子触发之所以这样,就是因为mouseenter不会冒泡跟mouseenter搭配 鼠标离开 mouseleave 同样不会冒泡
六、动画函数封装
6.1动画实现原理
核心原理:通过定时器 setInterval() 不断移动盒子位置。
实现步骤:
-
获得盒子当前位置
-
让盒子在当前位置加上1个移动距离
-
利用定时器不断重复这个操作
-
加一个结束定时器的条件
-
注意此元素需要添加定位,才能使用element.style.left
6.2 动画函数简单封装
6.2.1
注意函数需要传递2个参数,动画对象和移动到的距离。
如果多个元素都使用这个动画函数,每次都要var 声明定时器。我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。
核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性。
6.2.2缓动效果原理
缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
思路:
- 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
核心算法: (目标值 - 现在的位置 ) / 10 做为每次移动的距离 步长停止的条件是: 让当前盒子位置等于目标位置就停止定时器 注意步长值需要取整
6.2.3 动画函数添加回调函数
回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调。
回调函数写的位置:定时器结束的位置。
七、节流阀
防止轮播图按钮连续点击造成播放过快。
节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。
核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
开始设置一个变量 var flag = true;
If(flag) {flag = false; do something} 关闭水龙头
利用回调函数 动画执行完毕, flag = true 打开水龙头
移动端特效
一、触屏事件
1.移动端拖动元素
- touchstart、touchmove、touchend 可以实现拖动元素
- 但是拖动元素需要当前手指的坐标值 我们可以使用 targetTouches[0] 里面的pageX 和 pageY
- 移动端拖动的原理: 手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离
- 手指移动的距离: 手指滑动中的位置 减去 手指刚开始触摸的位置
拖动元素三步曲:
(1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置
(2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子
(3) 离开手指 touchend:
注意: 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();
2.移动端常见特效
2.1 classList 属性
classList属性是HTML5新增的一个属性,返回元素的类名。但是ie10以上版本支持。该属性用于在元素中添加,移除及切换 CSS 类。有以下方法
添加类:
element.classList.add(’类名’);
focus.classList.add(‘current’);
移除类:
element.classList.remove(’类名’);
focus.classList.remove(‘current’);
切换类:
element.classList.toggle(’类名’)
focus.classList.toggle(‘current’);
2.2 click 延时解决方案
移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。
解决方案:
-
禁用缩放。 浏览器禁用默认的双击缩放行为并且去掉 300ms 的点击延迟。
-
利用touch事件自己封装这个事件解决 300ms 延迟。
原理就是:
-
当我们手指触摸屏幕,记录当前触摸时间
-
当我们手指离开屏幕, 用离开的时间减去触摸的时间
-
如果时间小于150ms,并且没有滑动过屏幕, 那么我们就定义为点击
-
使用插件。 fastclick 插件解决 300ms 延迟。
3.插件的使用
1.确认插件实现的功能
2.去官网查看使用说明
3.下载插件
4.demo实例文件,查看需要引入的相关文件,并且引入
5.复制demo实例文件中的结构html,样式css以及js代码
4.Bootstrap
Bootstrap 是一个简洁、直观、强悍的前端开发框架,它让 web 开发更迅速、简单。
它能开发PC端,也能开发移动端
Bootstrap JS插件使用步骤:
1.引入相关js 文件
2.复制HTML 结构
3.修改对应样式
4.修改相应JS 参数
二、本地存储
1.本地存储特性
1、数据存储在用户浏览器中
2、设置、读取方便、甚至页面刷新不丢失数据
3、容量较大,sessionStorage约5M、localStorage约20M
4、只能存储字符串,可以将对象JSON.stringify() 编码后存储
2.window.sessionStorage
1、生命周期为关闭浏览器窗口
2、在同一个窗口(页面)下数据可以共享
3、以键值对的形式存储使用
存储数据* sessionStorage.setItem(key, value)
获取数据 sessionStorage.getItem(key)**
删除数据 sessionStorage.removeItem(key)
删除所有数据 sessionStorage.clear()**
3.window.localStorage
1、声明周期永久生效,除非手动删除 否则关闭页面也会存在
2、可以多窗口(页面)共享(同一浏览器可以共享)
3、以键值对的形式存储使用
存储数据* localStorage.setItem(key, value)
获取数据 localStorage.getItem(key)**
删除数据 localStorage.removeItem(key)
删除所有数据 localStorage.clear()**
JavaScript高阶
一、面向过程与面向对象
1.1面向过程
- 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。
1.2面向对象
- 面向对象是把事务分解成为一个个对象,然后由对象之间分工与合作。
1.3面向过程与面向对象对比
面向过程 | 面向对象 | |
---|---|---|
优点 | 性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程。 | 易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护 |
缺点 | 不易维护、不易复用、不易扩展 | 性能比面向过程低 |
2.对象与类
2.1对象
对象是由属性和方法组成的:是一个无序键值对的集合,指的是一个具体的事物
- 属性:事物的特征,在对象中用属性来表示(常用名词)
- 方法:事物的行为,在对象中用方法来表示(常用动词)
2.1.1创建对象
//以下代码是对对象的复习
//字面量创建对象
var ldh = {
name: '刘德华',
age: 18
}
console.log(ldh);
//构造函数创建对象
function Star(name, age) {
this.name = name;
this.age = age;
}
var ldh = new Star('刘德华', 18)//实例化对象
console.log(ldh);
如上两行代码运行结果为:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2vPdBWlD-1638882471145)(G:/html笔记/07-10 JavaScript网页编程/04-JavaScript高级资料/JavaScript 高级_day01/4-笔记/images/img3.png)]
2.2类
- 在 ES6 中新增加了类的概念,可以使用 class 关键字声明一个类,之后以这个类来实例化对象。类抽象了对象的公共部分,它泛指某一大类(class)对象特指某一个,通过类实例化一个具体的对象
2.2.1创建类
- 语法:
//步骤1 使用class关键字
class name {
// class body
}
//步骤2使用定义的类创建实例 注意new关键字
var xx = new name();
- 示例
// 1. 创建类 class 创建一个 明星类
class Star {
// 类的共有属性放到 constructor 里面
constructor(name, age) {
this.name = name;
this.age = age;
}
}
// 2. 利用类创建对象 new
var ldh = new Star('刘德华', 18);
console.log(ldh);
以上代码运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RqkvZzkz-1638882471146)(G:/html笔记/07-10 JavaScript网页编程/04-JavaScript高级资料/JavaScript 高级_day01/4-笔记/images/img4.png)]
通过结果我们可以看出,运行结果和使用构造函数方式一样
2.2.2类创建添加属性和方法
// 1. 创建类 class 创建一个类
class Star {
// 类的共有属性放到 constructor 里面 constructor是 构造器或者构造函数
constructor(uname, age) {
this.uname = uname;
this.age = age;
}//------------------------------------------->注意,方法与方法之间不需要添加逗号
sing(song) {
console.log(this.uname + '唱' + song);
}
}
// 2. 利用类创建对象 new
var ldh = new Star('刘德华', 18);
console.log(ldh); // Star {uname: "刘德华", age: 18}
ldh.sing('冰雨'); // 刘德华唱冰雨
以上代码运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KFrauwoz-1638882471147)(G:/html笔记/07-10 JavaScript网页编程/04-JavaScript高级资料/JavaScript 高级_day01/4-笔记/images/img5.png)]
注意哟:
- 通过class 关键字创建类, 类名我们还是习惯性定义首字母大写
- 类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象
- constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数
- 多个函数方法之间不需要添加逗号分隔
- 生成实例 new 不能省略
- 语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function
2.2.3类的继承
- 语法
// 父类
class Father{
}
// 子类继承父类
class Son extends Father {
}
- 示例
class Father {
constructor(surname) {
this.surname= surname;
}
say() {
console.log('你的姓是' + this.surname);
}
}
class Son extends Father{ // 这样子类就继承了父类的属性和方法
}
var damao= new Son('刘');
damao.say(); //结果为 你的姓是刘
以上代码运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1q6VlVt3-1638882471148)(G:/html笔记/07-10 JavaScript网页编程/04-JavaScript高级资料/JavaScript 高级_day01/4-笔记/images/img6.png)]
-
子类使用super关键字访问父类的方法
//定义了父类 class Father { constructor(x, y) { this.x = x; this.y = y; } sum() { console.log(this.x + this.y); } } //子元素继承父类 class Son extends Father { constructor(x, y) { super(x, y); //使用super调用了父类中的构造函数 } } var son = new Son(1, 2); son.sum(); //结果为3
注意:
-
继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
-
继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
-
如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用父类的构造函数,super 必须在子类this之前调用
// 父类有加法方法 class Father { constructor(x, y) { this.x = x; this.y = y; } sum() { console.log(this.x + this.y); } } // 子类继承父类加法方法 同时 扩展减法方法 class Son extends Father { constructor(x, y) { // 利用super 调用父类的构造函数 super 必须在子类this之前调用,放到this之后会报错 super(x, y); this.x = x; this.y = y; } subtract() { console.log(this.x - this.y); } } var son = new Son(5, 3); son.subtract(); //2 son.sum();//8
以上代码运行结果为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qNsoWNTT-1638882471149)(G:/html笔记/07-10 JavaScript网页编程/04-JavaScript高级资料/JavaScript 高级_day01/4-笔记/images/img7.png)]
-
时刻注意this的指向问题,类里面的共有的属性和方法一定要加this使用.
- constructor中的this指向的是new出来的实例对象
- 自定义的方法,一般也指向的new出来的实例对象
- 绑定事件之后this指向的就是触发事件的事件源
-
在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wmLw9zGI-1638882471150)(G:/html笔记/07-10 JavaScript网页编程/04-JavaScript高级资料/JavaScript 高级_day01/4-笔记/images/img2.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F7iWhuTr-1638882471151)(G:/html笔记/07-10 JavaScript网页编程/04-JavaScript高级资料/JavaScript 高级_day01/4-笔记/images/img1.png)]
-
3.面向对象版tab 栏切换
3.1功能需求
- 点击 tab栏,可以切换效果.
- 点击 + 号, 可以添加 tab 项和内容项.
- 点击 x 号, 可以删除当前的tab项和内容项.
- 双击tab项文字或者内容项文字可以修改里面的文字内容
3.2案例准备
- 获取到标题元素
- 获取到内容元素
- 获取到删除的小按钮 x号
- 新建js文件,定义类,添加需要的属性方法(切换,删除,增加,修改)
- 时刻注意this的指向问题
3.3切换
-
为获取到的标题绑定点击事件,展示对应的内容区域,存储对应的索引
this.lis[i].index = i; this.lis[i].onclick = this.toggleTab;
-
使用排他,实现只有一个元素的显示
toggleTab() { //将所有的标题与内容类样式全部移除 for (var i = 0; i < this.lis.length; i++) { this.lis[i].className = ''; this.sections[i].className = ''; } //为当前的标题添加激活样式 this.className = 'liactive'; //为当前的内容添加激活样式 that.sections[this.index].className = 'conactive'; }
3.4添加
-
为添加按钮+ 绑定点击事件
this.add.onclick = this.addTab;
-
实现标题与内容的添加,做好排他处理
addTab() { that.clearClass(); // (1) 创建li元素和section元素 var random = Math.random(); var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"> </span></li>'; var section = '<section class="conactive">测试 ' + random + '</section>'; // (2) 把这两个元素追加到对应的父元素里面 that.ul.insertAdjacentHTML('beforeend', li); that.fsection.insertAdjacentHTML('beforeend', section); that.init(); }
3.5删除
-
为元素的删除按钮x绑定点击事件
this.remove[i].onclick = this.removeTab;
-
获取到点击的删除按钮的所在的父元素的所有,删除对应的标题与内容
removeTab(e) { e.stopPropagation(); // 阻止冒泡 防止触发li 的切换点击事件 var index = this.parentNode.index; console.log(index); // 根据索引号删除对应的li 和section remove()方法可以直接删除指定的元素 that.lis[index].remove(); that.sections[index].remove(); that.init(); // 当我们删除的不是选中状态的li 的时候,原来的选中状态li保持不变 if (document.querySelector('.liactive')) return; // 当我们删除了选中状态的这个li 的时候, 让它的前一个li 处于选定状态 index--; // 手动调用我们的点击事件 不需要鼠标触发 that.lis[index] && that.lis[index].click(); }
3.6编辑
-
为元素(标题与内容)绑定双击事件
this.spans[i].ondblclick = this.editTab; this.sections[i].ondblclick = this.editTab;
-
在双击事件处理文本选中状态,修改内部DOM节点,实现新旧value值的传递
editTab() { var str = this.innerHTML; // 双击禁止选定文字 window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty(); // alert(11); this.innerHTML = '<input type="text" />'; var input = this.children[0]; input.value = str; input.select(); // 文本框里面的文字处于选定状态 // 当我们离开文本框就把文本框里面的值给span input.onblur = function() { this.parentNode.innerHTML = this.value; }; // 按下回车也可以把文本框里面的值给span input.onkeyup = function(e) { if (e.keyCode === 13) { // 手动调用表单失去焦点事件 不需要鼠标离开操作 this.blur(); } } }