JavaScript - 基础+WebAPI(笔记)
前言:
- 求关注😭
- 本篇文章主要记录以下几部分:
- 基础:
- 输入输出语法;
- 数据类型;
- 运算符;
- 流程控制 - 分支语句;
- 流程控制 - 循环语句;
- 数组 - 基础;
- 函数 - 基础;
- 对象 - 基础;
- Web API:
- DOM;
- DOM事件基础(事件监听、常用事件、事件对象);
- DOM事件进阶(事件流、事件委托);
- 日期对象;
- 节点操作;
- M端事件;
- JS插件;
- window对象;
- 本地存储;
- 正则表达式;
- 基础:
- 以下部分请移步JavaScript - 进阶+高级(笔记):
- 进阶:
- 作用域;
- 函数进阶(函数提升、函数参数、箭头函数);
- 解构赋值;
- 对象进阶(构造函数、实例成员、静态成员);
- 内置构造函数(Object、Array、String、Number);
- 编程思想;
- 构造函数;
- 原型
- 高级:
- 深浅拷贝;
- 异常处理;
- this指向;
- 性能优化(防抖、节流);
- 进阶:
壹、❗❗ JavaScript基础
- HTML 表示网页的 结构
- CSS 表示网页的 样式
- JavaScript 表示网页的 行为
- 浏览器内核 = 渲染引擎 + JS引擎
- JavaScript的组成
- ECMAScript — JS的基础语法
- Web APIs
- DOM — 操作文档流的属性和方法(文档对象模型)
- 是HTML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式,可以在程序中对该结构进行访问,从而改变文档的结构、样式和内容。DOM将文档解析为一个由节点和对象(包含属性和方法)组成的结构集合。简言之,它会将 web页面和 程序 连接起来。进而操作网页的内容,实现各种功能和部分特效
- BOM — 操作浏览器的属性和方法(浏览器对象模型)
-
- DOM — 操作文档流的属性和方法(文档对象模型)
- JS的本质: 通过 JS 的语法,让 浏览器 发生变换,让 文档 发生变化。
一、JavaScript书写位置
- 行内 JavaScript
- 内部 JavaScript
- 外部 JavaScript
二、输入输出语法
- 小括号里面只要 不是纯数字 和 变量 必须要用 引号包裹(单、双、反)
alert() --- 警示框 prompt() --- 浏览器弹出输出框,用户可以输入信息 console.log() --- 控制台输出 document.write() --- 在文档页面输出(识别标签)
- 代码展示:
alert('你好, js'); prompt('JavaScript 基础'); console.log('它~会魔法吧~'); document.write('javascript我来');
三、字面量、变量、常量
3.1 字面量
- 用来在计算机中描述 事 / 物
- [ ] : 数组字面量
- { } : 对象字面量
- 数字字面量:数字
- 字符字面量:字符串
- 布尔字面量:布尔值
3.2 变量
- 变量:用来 存储数据 的 容器
- 变量的本质:内存里的一块空间,用来 存储数据
- 变量 必须 先声明 后使用
- 变量的初始化: 声明变量 并 赋值
- 变量命名规则:变量名只能是 数字、大小写字母、美元符($)、下划线组成(⚠ 不能以数字开头)
- ⚠ 不能使用 name 作为变量名 (name会将 数字型 转为 字符型)
- 声明 变量使用 let
- 代码展示:
// 声明变量// 声明变量不赋值 let a // 变量的初始化 --- 声明变量并赋值 let age = 18 // 声明多个变量(用逗号隔开)--- 不推荐 let a = 18, b = 'pink' // 更新变量 let age = 18age = 19 console.log(age) // 19// 用变量赋值 let myFood = '香蕉' let youFood = myFood console.log(youFood) // 香蕉
3.2.1 var 和 let 的区别
- var
- 可以 先使用 再声明
- var声明过的变量可以重复声明
- 存在变量提升、没有块作用域等等。
- let / const
- 必须 先声明 后使用
- 不能 声明 重复变量
- 不存在变量提升
- 使用了 let / const 声明的变量存在块作用域
- const声明变量的时候必须初始化
3.3 常量
- 声明常量使用 const
- ⚠ 常量不允许重新赋值,声明的时候必须赋值 (必须初始化)
- 注意:
const num = 10; num = 10; console.log(num); // 报错 - 常量不允许重新赋值
- 注意:
四、❗❗ 数据类型
- 1️⃣ 值类型 (基本数据类型)(6)
number
— 数字型string
— 字符串型boolean
— 布尔型undefined
— 未定义型null
— 空类型symbol
(了解)bigint
- 2️⃣ 引用数据类型 (复杂数据类型)(3)
object
— 对象function
– 函数array
— 数组
4.1 数字型 - number
- 数字型 = number + NaN
Number
一切十进制表示的数字
Number.MAX_VALUE // 数字中的最大值
Number.MIN_VALUE // 数字中的最小值
Infinity // 无穷大
-Infinity // 无穷小
NaN // 非数值isNaN(数据) 这个方法用来判定非数字,并且返回一个值,如果是数字返回 false,如果不是数字返回 true
console.log(2 - NaN) // NaN
console.log('粘性' + NaN) // NaN
console.log(NaN === NaN) // NaN
4.2 字符串型 - string
- 用引号(单引号 / 双引号 / 反引号)包裹的都是字符串
4.2.1 字符串的长度
lengtn 属性
let strMsg = (`扶我起来,我还能干!`)
console.log(strMsg.length) // 显示 10
4.2.2 字符串的拼接
- 多个字符串之间可以使用 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 新的字符串
- 拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
- “+” 数字相加,字符相连
4.2.3 ❗❗ 模板字符串
- 使用 反引号(``) 包裹
- 模板字符串可以 嵌套变量
- 代码展示:
let myName = `邵秋华` let age = 22 let str = `扶我起来,我还能干!` document.write(`我叫${myName},今年${age}岁了,我的座右铭是${str}`)
- 代码展示:
4.2.4 ❌ 转义字符
4.3 布尔型 - boolean
- 布尔类型 有 两个值,true 和 false,其中 true 表示 真,而 false 表示 假
- 布尔型 和 数字型 相加 的时候,
true = 1
,false = 0
- ❗ 除了
0
、''
、undefined
、null
、NaN
、false
转换为布尔值后为 假,其余都为真
4.4 未定义类型 - undefined
- 只声明变量,不赋值 的情况下,变量的默认值为
undefined
undefined
这里本该有一个值,但是没有,就是undefined
- ⚠
数字 + undefined = NaN
- ⚠ 注意:
- ⚠ 对 undefined 的任何操作都是NaN,除了拼接字符串
- 出现情况:
- 声明变量未赋值
- 数组 里面 没有 某个 元素
- 对象 里面 没有 某个 属性 或 方法
- 函数
- 形参多于实参(没有赋值的形参默认值是 undefined)
- 函数未指定返回值(没有 return 关键字)
console.log(undefind + 1) // NaN
condsole.log(undefined + 'purple') // undefinedpurple
console.log(typeof(undefined)) //undefined
4.5 空类型 - Null
- Null 这里有一个值,有一个空值
- ✅参与 数学运算 的时候,
null = 0
console.log(null + 1) // 1
console.log(null + 'purple') // nullpurple
console.log(typeof(null)) // object
4.6 null 和 undefined 区别:
- undefined 表示 声明了一个变量,但是没有赋值
-
let num console.log(undefined + 1) // NaN
-
- null 表示 声明了一个变量 并且 赋值了,但是内容为空
-
let num = null console.log(null + 1) // 1
-
- ✅注意:
- ⚠
null
和undefined
值相等,数据类型不相等
console.log(null == undefined) // true
- ⚠
4.7 检测数据类型
- 1️⃣ 作为运算符:
typeof 数据
- 以 字符串 的形式 给你变量的数据类型
- ⚠ 使用 typeof 检测 错误类型 为 undefined 的代码不会报错,检测结果是 undefined
- 2️⃣ 函数形式:
typeof(数据)
(推荐使用)- 以字符串的形式给你变量的数据类型
- 先运算小括号里面结果,然后去检测结果的数据类型
- 代码展示:
let num = 10; console.log(typeof num); // number let str = 'purple'; console.log(typeof str); //string let flag = true; console.log(typeof flag); //boolean let i = undefined; console.log(typeof i); //undefined let timer = null; console.log(typeof timer); //object // 注意 console.log(typeof (a)); // undefined
- 3️⃣
instanceof
- 用于检测构造函数的
prototype
属性是否出现在某个实例对象的原型链上。 - 返回值:布尔值(true / false)
- 用于检测构造函数的
- 4️⃣ 究极方法:
Object.prototype.toString()
- 可以通过
toString()
来获取每个对象的类型。为了每个对象都能通过Object.prototype.toString()
的检测,需要以Function.prototype.call()
或Function.prototype.apply()
的形式来调用,传递要检查的对象作为第一个参数。 - 返回值:[ object type ]
- 代码展示:
// 引用数据类型 const obj = {uname: '迪迦', age: 22}; console.log(Object.prototype.toString.call(obj)); // [object Object] const arr = [1, 2, 3]; console.log(Object.prototype.toString.call(arr)); // [object Array] const fn = function () { console.log(1) }; console.log(Object.prototype.toString.call(fn)); // [object Function]// 基本数据类型 console.log(Object.prototype.toString.call(123)); // [object Number] console.log(Object.prototype.toString.call('123')); // [object String] console.log(Object.prototype.toString.call(false) ); // [object Boolean] console.log(Object.prototype.toString.call(undefined)); // [object Undefined] console.log(Object.prototype.toString.call(null)); // [object Null]
- 可以通过
4.8 数据类型转换
4.8.1 转数字
- 1️⃣
parseInt(string)
可以把 字符串型 转换为 整数型(不识别小数点)- 从 第一个字符开始 取第一个整数,如果取不到就是NaN
- ⚠ 转换的字符开头如果不是数字,就是NaN
- 代码展示:
console.log(parseInt('3.14')) //3(取整数位) console.log(parseInt('3.99')) //3(取整数位) console.log(parseInt('120px')) //120 (自动去除单位,前面必须是数字) console.log((parseInt'rem120px')) //NaN console.log(parseInt(true)) //NaN console.log(parseInt(null)); // NaN
- 2️⃣
parseFloat(string)
可以把 字符串型 转换为 浮点型(识别小数点)- 从第一个字符开始取第一个小数,如果取不到就是NaN
- ⚠ 转换的字符开头如果不是数字,就是NaN
- 代码展示:
console.log(parseFloat('3.14')); //3.14 console.log(parseFloat('3.99')); //3.99 console.log(parseFloat('120px')); //120 (自动去除单位,前面必须是数字) console.log(parseFloat('rem120px')); //NaN console.log(parseFloat(true)) //NaN console.log(parseFloat(null)); // NaN
- ⚠ 注意:
parseInt 和 parseFloat 单词的大小写
- 3️⃣
Number(string)
强制转换- 转换的数据中不能包含非数字,如果有就是NaN
- 识别小数点
- 代码展示:
let num = '123'; console.log(Number(num)); //123 console.log(Number('12')); //12 console.log(NUmber('123.123'); // 123.123 console.log(Number('123abc'); //NaN console.log(Number(null)); // 0 console.log(Number(true)); // 1 console.log(Number(false)); // 0
- 4️⃣ 利用了算术运算 **+(正号) - * / % ** 隐式转换
- 代码展示:
console.log('12' - 0); //12 (先将 '12' 转换成数字型在进行减) console.log('123' - '120'); //3 console.lof('123' * 1); //123 console.log(+'123') //123 + 号作为正号解析可以转换成数字型(单用)
let year = prompt('请输入您的出生年份:'); //let age = 2022 - year; alert('您今年:' + (2022 - year) + '岁了');
- 注意:
- 隐式转换是我们在进行算数运算的时候,JS 自动转换了数据类型
- 代码展示:
let num1 = prompt('请输入第一个数据:'); //得到的num1是字符型的 let num2 = prompt('请输入第二个数据:'); //得到的num2是字符型的 let result = parseInt(num1) + parseInt(num2); alert(parseInt(num1) + '+' + parseInt(num2) + '=' + result);/* let num1 = +prompt('请输入第一个数据:'); let num2 = +prompt('请输入第二个数据:'); let result = num1 + parseInt(num2); */
- 代码展示:
- ✅ 注意:
- 有字符串的加法 ‘’ + 1,结果是 ‘1’
- 减法 只能用于数字,它会使 空字符串 ‘’ 转换为 0
- null 经过 数字转换 之后会变为 0
-
parseInt(null); // NaN parseFloat(null); // NaN Number(null); // 0
-
- undefined 经过 数字转换 之后会变成 NaN
- undefined 做任何操作都是 NaN 除了拼接字符串
null == undefined // true 值都是空 null === undefined // false 数据类型不一样
4.8.2 转字符串
- 1️⃣ String(数据)
- 返回值:转换好的数据
- 代码展示:
console.log(String(123)) // '123'
- 2️⃣ 数据.toString()
- 返回值:转换好的数据
- ⚠ **注意:**需要 配合 变量 使用、
- 代码展示:
let num = 123 console.log(num.toString()) // '123'
- 3️⃣ +(加号)
- 字符串的拼接
- 代码展示:
console.log(123 + '') // '123'
toString() 和 String() 使用方式不一样。
三种转换方式,我们更喜欢用第三种加号拼接字符串转换方式, 这一种方式也称之为隐式转换。
4.8.3 转布尔
- Boolean(数据)
- 返回值:转换好的数据
- ⚠ 注意:代表 空、**否定的值 **会被 转换成 false
- ‘’、 0、 NaN、 null、 undefined、 false
- 代码展示:
console.log(Boolean('')) // false console.log(Boolean(0)) // false console.log(Boolean(NaN)) // false console.log(Boolean(null)) // false console.log(Boolean(undefined)) // false console.log(Boolean(false)) // false注意: // 两个等号值比较 值 // null 和 undefined 都是空 console.log(null == undefined) // true
五、运算符
5.1 算术运算符
5.2 递增递减运算符
5.2.1 前置++
- 先自加,后返回值
- 先自加,后运算(++在前 先加)
let num = 10;
alert(++num + 10); // 21
5.2.2 后置++
- 先原值运算,后自加(++在后 后加)
- 先表达式返回原值,后面变量再自加1
let num = 10;
alert(10 + num++); // 20
- **注意:**前置++ 和 后置++ 单独书写没有差别
5.2.3 前置–
先自减,后运算(先已后人)
let num = 10;
alert(--num + 10); // 19
5.2.4 后置–
先原值运算,后自减(先人后己)
let num = 10;
alert(10 + num--); // 20
let a = 10;
++a; // ++a = 11 a = 11
let b = ++a + 2; // a = 12 ++a = 12
console.log(b); // 14let c = 10;
c++; // c++ = 11 c = 11
let d = c++ + 2; // c++ = 11 c = 12
console.log(d); // 13let e = 10;
let f = e++ + ++e;
// e++ = 10 e = 11
// e = 12 ++e = 12
console.log(f); // 22
5.3 比较运算符
- 注意:
- 比较运算符有隐式转换
-
console.log(2 == '2') // true
- ⚠ 特殊说明:
- 如果是数字和“其他值”的比较,则其他值会自动转换成数字去比较
- 涉及到“NaN”都是false
- 如果是”字符串“和“字符串”比较,则会比较每一个字符的ASCII码
- 如果是布尔值参与比较,布尔值会自动转换成数字0和1
- 数字只有0是假,其余为真
- 字符串只有’'(空字符串)是假,其余都为真
5.4 ❗ 逻辑运算符
- 1️⃣ && 与 有 一个 是 false ,得到的 结果 就是 false ;只有 两侧 都是 true 的时候,才可以到的 true
- 2️⃣ || 或 有一个 是 true ,得到的结果就是 true ;只有 两侧 都是 false 的时候,才得到 false
- 3️⃣ ! 非 取反(双取反可以转布尔)
- ⚠ 注意: 逻辑运算符 优先级: ! > && > ||
5.4.1 短路运算(逻辑中断)
- 短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值;
- 1️⃣ 逻辑与-语法:(一假则假)
-
表达式1 && 表达式2如果 表达式1的值 为 真,则返回 表达式2如果 表达式1的值 为 假,则返回 表达式1 (后面的表达式不再执行)两侧都为真,返回第二个
-
- 2️⃣ 逻辑或-语法: (一真则真)
-
表达式1 || 表达式2如果 表达式1的值 为 真,则返回 表达式1 (后面的表达式不再执行)如果 表达式1的值 为 假,则返回 表达式2 两侧都为真返回第一个
-
5.5 赋值运算符
5.6 ❗ 运算符优先级
- 一元运算符 里 逻辑非 优先级最高
- 逻辑与 比 逻辑或 优先级 高
-
console.log( 4 >= 6 || '人' != '阿凡达' && !(12 * 2 == 144) && true) // true let num = 10 console.log( 5 == num / 2 && (2 + 2 * num).toString() === ‘22’) // true let a = 3 > 5 && 2 < 7 && 3 == 4 console.log(a) // false let b = 3 <= 4 || 3 > 1 || 3 != 2 console.log(b) // true let c = 2 === "2" console.log(c) // false let d = !c || b && a console.log(d) // true
六、流程控制 - 分支语句
- 表达式和语句的区别:
- 表达式:表达式可被求值,可以写在赋值语句的右侧(运算符和数据组成的式子)
- 语句:不一定有值(可以被执行的代码)
6.1 if 语句
-
条件为 true 的时候,大括号里面的代码才会执行
-
小括号里的结果若不是布尔类型时,会发生隐式转换转为布尔类型
-
⚠ if分支语句,如果前面的条件被满足,后面的代码就不执行了
-
if (条件) {满足条件要执行的代码 }
-
if (条件) {满足条件要执行的代码 } else {条件不满足时要执行的代码 }eg: // 能被4整除但不能被100整除,或者被400整除的年份是闰年,否则都是平年 let year = +prompt('请输入年份:') if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {alert(`&{year}是闰年`) } else {alert(`&{year}是平年`) }
-
if (条件表达式1) {满足条件1要执行的代码 } else if (条件表达式2) {满足条件2要执行的代码 } else if (条件表达式n) { 满足条件n要执行的代码 } else {所有条件都不满足时要执行的代码 }
6.2 三元运算符
- 语法结构:
条件表达式 ? 表达式1 : 表达式2
- 执行思路:
- 如果 条件表达式 结果 为真,则 返回 表达式1 的值,如果 条件表达式 结果 为假,则 返回 表达式2 的值
- 代码展示:
let time = prompt('请您输入一个 0 ~ 59 之间的一个数字') // 三元表达式 表达式 ? 表达式1 :表达式2 let result = time < 10 ? '0' + time : time // 把返回值赋值给一个变量 alert(result)/* 如果输入的数字小于10,就在该数字前面加一个0,否则原样输出该数字 */ let num = prompt('请输入数字:') let result = num < 10 ? '0' + num : num alert(result)
6.3 switch 语句
- 表达式有一个返回值,**返回值 **会和 value 做匹配(必须是 全等 的关系),如果匹配上了就执行对应的语句 ,如果都匹配不上就执行default里的语句
- 语法:
switch ( 表达式 ) {case value1:满足value1执行的代码breakcase value2:满足value2执行的代码breakdefault:所有条件都不满足时要执行的代码 }
- ⚠ 注意:
- 每一个 case 和 表达式 必须是 ===(值 和 数据类型 都相等) 才叫满足
- switch 语句,只能判断一些准确的值,不能判断范围
- 实际开发过程中 表达式 我们经常 写成 变量
- 代码展示:
let num1 = +prompt('请输入第一个数字:') let sp = prompt('请输入 + - / * 其中一个:') let num2 = +prompt('请输入第二个数字:')switch (sp) {case '+':let add = num1 + num2alert(`${num1} + ${num2} = ${add}`)breakcase '-':let dif = num1 - num2alert(`${num1} - ${num2} = ${dif}`)breakcase '*':let bus = num1 * num2alert(`${num1} x ${num2} = ${bus}`)breakcase '/':let pro = num1 / num2alert(`${num1} ÷ ${num2} = ${pro}`)breakdefault:alert('请输入正确的运算符')break }
七、流程控制 - 循环语句
7.1 循环成立的条件
- 初始值 作为循环的开始
- 条件判断 决定要不要继续循环
- 要重复执行的代码
- 改变初始值 为了让循环有结束
7.2 ❗ for 循环
- 语法结构:
for (初始化变量; 条件表达式; 操作表达式) {循环体 }
- 初始化变量:通常被用于初始化一个计数器,这个变量帮我们来记录次数。
- 条件表达式:用于确定每一次循环是否能被执行。如果结果是 true 就继续循环,否则退出循环。(终止条件)
- 操作表达式:每次循环的最后都要执行的表达式。通常被用于更新或者递增计数器变量。当然,递减变量也是可以的。(递增或者递减)
- 代码展示:
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head><body></body><script>// 求1-100之间所有数字的和let sum = 0;let average = 0;for (let i = 1; i<= 100; i++) {sum += i}average = sum / 100;console.log('1-100之间所有数字的和为:' + average); // 求1-100之间所有偶数的和和奇数的和let even = 0;let odd = 0;for (i = 1; i <= 100; i++) {// 第一种if (i % 2 == 0) {even = even + i;} else {odd += i;}//第二种if (i % 2 == 0) {even = even + i;}odd = sum - even;}console.log('1-100之间所有偶数的和为:' + even + '\n' + '1-100之间所有奇数的和为:' + odd);// 求1-100之间所有能被3整除的数字的和let odd_num = 0;for (let i = 1; i <= 100; i++) {if (i % 3 == 0) {odd_num = odd_num + i;}}console.log('1-100之间所有能被3整除的数字的和为:' + odd_num);//弹出输入框,输入一共有n个学生,然后弹出n个输入框,输入每个学生的成绩,最后输出总成绩和平均成绩let frequency = prompt('请输入有多少个学生:');let score = 0;for (let i = 1; i <= frequency; i++) {let a = prompt('请输入第' + i + '个同学的成绩:');// 从 prompt 获取到的数据是 String 类型的,不能直接和数字进行相加score = score + parseFloat(a);}alert('该班总成绩是:' + score);alert('该班平均成绩是:' + (score / frequency));//一行打印五个星星let str = ' ';for (let i = 1; i <=5; i++) {str = str + '⭐';}console.log(str); </script> </html>
7.3 ❗ 双重for循环
-
//打印n行m列的星星 let rows = +prompt('请输入需要打印几行的星星:'); let cols = +prompt('请输入需要打印几列的星星:'); let str = ''; for (let i = 1; i <=rows; i++) {for (let j = 1; j <= cols; j++) {str += '⭐';}str += '\n'; } console.log(str);
- 冒泡排序:
// 外层for循环:控制已经排序好的元素的个数 // 内层for循环:控制每排序好一个元素需要比较几次 const arr = [1, 7, 3, 9, 5, 2, 6, 4, 8]; for (let i = 0; i < arr.length - 1; i++) {for (let j = 0; j < arr.length - i - 1; j++) {if (arr[j] > arr[j + 1]) {let temp = arr[j + 1];arr[j + 1] = arr[j];arr[j] = temp;}} } console.log(arr);
7.4 while循环
- 循环三要素:
- 变量初始值
- 终止条件
- 变量变化量
- 语法:
let n = 1while ( 循环条件 ) {重复执行的代码n++}
7.5 ❗ continue 和 break
- continue
- 退出本次循环,继续下一次循环
- 一般用于排除或者跳过某一个选项的时候
- continue 在循环节构中用来跳过本次循环中剩余的代码,并且在条件求值为真的时开始下一次循环。
- 不能省略 continue 后面的分号(导致胡乱)
- continue 后面 的 代码 不会 再 执行
- break
- 退出整个循环(结束循环)
- 一般用于结果已经得到,后续的循环不需要的时候
- 在一些计算机语言中 break 是保留字,其作用大多数情况下是终止上一层循环。
7.6 JS标记语法
-
JS标记语法 here: for (let i = 1; i <= 5; i++) {for (let j = 1; j <= 3; j++) {if (i === 3 && j === 2) {console.log('看到半条虫子')break here}console.log('吃的第 ' + i + ' 个包子得第 ' + j + ' 口')}console.log('=================') }
八、❗❗ 数组 - 基础
- 一种 有序 的数据集合
8.1 创建数组
8.1.1 字面量创建
let 数组名 = [数据1, 数据2, …, 数据n]
let arr = ['name', 'Jack', 'age', 20, 'gender', '男']
8.1.2 内置构造函数创建
//没有参数表示空数组
let arr = new Array() //一个参数表示数组的长度
let arr = new Array(100) //多个参数表示都是数组里面的数据,没有表示长度的参数
let arr = new Array(10, 20, 30)
arr.length = 2 //删除最后一个
arr.length = 5 //后面的两个用空补齐
console.log(arr[2]) //读取里面的额第三个数据
8.2 ❗❗ 遍历数组
能够获取数组里面的每个元素
8.2.1 for
- 格式:
for (let i = 0; i < 数组名.length; i++) {// 执行的操作// console.log(数组名[i]) }
8.2.2 forEach
- 取代 for 循环
- 语法:
数组.forEach(function (item, index, arr) { } )-> item :数组里面的每一项-> index :数组里面每一项的索引-> arr : 原始数组
- ⚠ 没有 返回值
- forEach中的 return 等同于 for循环的 continue
- 终止forEach循环:try - catch
try {[1, 2, 0, 3].forEach(item => {console.log(item)if (item === 1) {console.log(item)throw Error()}}) } catch (error) {console.log('终止循环') }// 打印结果 // 1 // 1 // z
8.2.3 for of
- 遍历 可迭代 的数据:数组,伪数组,字符串
- 遍历的是数组、伪数组、字符串的值
- 语法:
for (let item of arr) {console.log(item) // item -> 数据里面的每一项 }
8.3 数组的增删查改
8.3.1 增
- 1️⃣✔数组.push() 方法:将 一个或多个元素 追加 **到 数组 的 末尾 ,并 返回 追加元素后数组 的 长度
- 语法:数组.push(数据1, 数据2, … ,数据n)
- 返回值: 追加元素后数组的长度
- ⚠改变原始数组
- 2️⃣ 数组.unshift() 方法:将 一个或多个元素 插入 到 数组 的 开头,并 返回 插入元素后数组 的 长度
- 语法:数组.unshift(数据1, 数据2, …, 数据n)
- 返回值: 插入元素后数组的长度
- ⚠改变原始数组
- 见代码展示
8.3.2 删
- 1️⃣ 数组.pop() 方法:从数组中 删除 最后一个 元素
- 语法:数组.pop()
- 返回值: 被删除的元素
- ⚠改变原始数组
- 2️⃣ 数组.shift() 方法:从数组中 删除 第一个元素
- 语法:数组.shift()
- 返回值: 被删除的元素
- ⚠改变原始数组
- 3️⃣ ✔数组.splice(start, deleteCount) 方法:删除 数组 里 指定的元素
- 语法:数组.splice(开始索引,删除几个)
- ⚠🔺 注意:包含开始索引 对应 的 元素
- deleteCount:表示要移除的数组元素的个数(如果 省略 则 默认 从 指定的起始位置 删除到最后)
- 返回值: 新数组(将删除的元素放到这个新数组里面)
- ⚠改变原始数组
- 语法:数组.splice(开始索引,删除几个)
- 见代码展示
8.3.3 查
- 见代码展示
8.3.4 改
- 见代码展示
代码展示:
<script>let arr = ['pink', 'red'];// 增加// 方案一:数组.push()方法语法:arr.push(元素1, 元素2, …, 元素n);追加数组 的同时 有一个 返回值 是 追加以后 的 数组长度console.log(arr.push('green', 'hotpink', 'deeppink')); // 5console.log(arr); // ['pink', 'red', 'green', 'hotpink', 'deeppink']// 方案二:数组.unshift()方法语法:arr.unshift(元素1, 元素2, …, 元素n);console.log(arr.push('green', 'hotpink', 'deeppink')); // 5console.log(arr);// ['green', 'hotpink', 'deeppink', 'pink', 'red']// 删除// 方案一:数组.pop()console.log(arr.pop()); // green// 方案二:数组.shift()console.log(arr.shift()); // red// 方案三:数组.splice(起始位置的索引, 删除几个元素)// 从索引号0的位置开始,删除两个元素console.log(arr.splice(0, 2)); // ['hotpink', 'deeppink']// 查询 --- 利用数组的索引进行查找console.log(arr[0]); // pink// 修改 --- 利用 对数组进行遍历,然后和字符串拼接,重新赋值给数组里的元素// 方案一:arr[0] = 'blue';arr[1] = 'purple';//方案二:for (let i = 0; i < arr.length; i++) {arr[i] += '老师';}console.log(arr)
</script>
九、❗❗ 函数
- 函数:执行特定任务的代码块
9.1 函数的声明和使用
9.1.1 函数的声明
- 函数命名规范:
- 和变量命名基本一致
- 小驼峰式命名法
- ⚠ 前缀应该为动词
-
can --- 判断是否可执行某个动作 has --- 判断是否含义有某个值 is --- 判断是否为某个值 get --- 获取某个值 set --- 设置某个值 load --- 加载某些数据
-
- 1️⃣ 具名函数
- 语法:
function 函数名() {函数体 }
- ⚠ 注意:可以 后声明先调用 ,也可以 先声明后调用
- 语法:
- 2️⃣ 匿名函数
- 使用方式:
- ① 函数表达式:
- 语法:
let 函数名 = function () {// 函数体 }
- 语法:
- ② 立即执行函数:
- 语法:
!(function (实参) { 函数体 })(实参); !(function (实参) { 函数体 } (实参));
- ⚠ 注意: 立即执行函数 末尾 必须加 分号
- 语法:
- ① 函数表达式:
- ⚠ 注意:
- 函数名() — 表示调用这个函数
- 函数名 — 表示一个变量,代表这个函数
- 使用方式:
- 代码展示:
function getSum() {let sum = 0for (let i = 1; i <= 100; i++) {sum += sum}document.write(sum) }
9.1.2 函数的使用
- 函数的调用:
-
函数名()
-
- ⚠ 注意: 声明的函数 必须 调用 才会真正执行,使用 () 调用函数
- 函数 一次声明 可以 多次调用 ,每一次函数调用函数体里面的代码会重新执行一次
- 代码展示:
function getSum() {let sum = 0for (let i = 1; i <= 100; i++) {sum += sum}document.write(sum) } getSum() // sum = 5050
- 代码展示:
9.1.3 函数传参
- 声明语法:
-
function 函数名(参数列表) {函数体 }
- 传入数据列表
- 声明这个函数需要传入几个数据
- 多个参数之间用 逗号 隔开
- 代码展示:
function getSum(start, end) {// 形参 - 形式上的参数let sum = 0for (let i = start; i <= end; i++) {sum += sum}document.write(sum) }
-
- 调用语法:
-
函数名(传递的参数列表)
- 代码展示:
getSum(10, 20) // sum = 33 // 实参 - 实际的参数
- 形参:
- 形式上的参数 — 写在 函数声明阶段 的 小括号 里
- 本质:就是在函数内部声明的变量(局部变量)
- 作用:接受实参传递的参数
- 如果既没有实参传递,也没有设置默认值,就是 undefined
- 实参:
- 实际上的参数 — 写在 **函数调用阶段 **的 **小括号 **里
- 实参 可以是 变量
- 作用:给形参赋值
-
- 参数默认值:
- 在调用的过程中,如果有参数传递过来,就用传递过来的;如果没有参数传递过来就用默认的
- ⚠ **注意:**若没设置默认值,默认就是 undefined
- 代码展示:
function getSum(x = 0, y = 0) {// 小括号里写了就不用写// 推荐用逻辑中断// x = x || 0// y = y || 0document.write(x + y) }getSum() // 0 getSum(1, 2) // 3
9.1.4 函数的返回值:
- 语法:返回给调用者(当调用某个函数,这个函数会返回一个结果出来)
return 要返回的数据
- ⚠ 注意:
- 在 函数体 中使用 return 关键字能 将内部的执行结果 交给 函数外部 使用
- 所以 return 后面的数据不要换行写
- ⚠ return 和 要返回的数据不能换行写(模板字符串、函数除外)
- 一个函数只能有一个return(因为第一个return后面的代码就不执行了)
- 如果 函数 没有指定 return,这种情况函数 默认返回值 为 undefined
- 函数如果有 多个返回值 ,用 中括号包裹,中间 用 逗号隔开 (返回的是一个新数组)
- 代码展示:
-
function fn() {return 20 // 把 结果(20) 返回给 fn } fn() // 相当于执行了 fn() = 20 (fn()是函数的调用者) console.log(fn()) // 20// 求两个数的最大值 function getMax(x = 0, y = 0) {return x > y ? x : y }getMax(65, 99) // 99 let max = getMax(65, 99) console.log(max)
- 求数组里面的最大值和最小值
- 代码展示:
// 声明一个 getArrValue函数 function getArrValue(arr = []) {let max = arr[0]let min = arr[0]//遍历数组for (let i = 0; i < arr.length; i++) {// 最大值if (max < arr[i]) {max = arr[i]}// 最小值if (min > arr[i]) {min = arr[i]}}// return 返回多个值写法return [max, min] }let newArrr = getArrValue([23, 56, 32, 198, 0, 5, -98])console.log(`数组中的最大值是:&{newArr[0]}`) // 198 console.log(`数组中的最小值是:&{newArr[1]}`) // -98
- 时间转换 + 补0
- 代码展示:
function getTime(t = 0) {let second = parseInt(t % 60)let minute = parseInt(t / 60 % 60)let hour = parseInt(t / 60 / 60 % 24)// if条件分支语句/* if (second < 10) {second = '0' + second}if (minute < 10) {minute = '0' + minute}if (hour < 10) {hour = '0' + hour} */// 三元表达式second < 10 ? second = '0' + second : secondminute < 10 ? minute = '0' + minute : minutehour < 10 ? hour = '0' + hour : hourreturn `${t}秒 = ${hour}小时${minute}分钟${second}秒` }let str = getTime(+prompt('请输入秒数:')) // 1000 document.write(str) // 1000秒 = 00小时16分钟40秒
-
- ⚠ 函数注意点:
- 两个函数名相同的函数,后面的会覆盖前面的
- 两个函数体相同的匿名函数不是同一个函数
- 传递参数
- 形参过多会自动填上 undefined
- 实参多于形参,剩余的实参不参与运算
- 实参少于形参,多于的形参使用默认值 undefined
- 函数一旦碰到 return 就不会往下执行,函数的结束用 return
- break 和 return 的区别:
- break:结束 的是 循环 和 switch
- return:结束 的是 函数 和 for循环
9.2 作用域基础
作用域: 变量的 可用性范围 就是 作用域 (提高程序逻辑的局部性)
9.2.1 全局作用域
- 全局有效
- 作用与所有代码执行的环境(整个script标签内部)或者一个独立的js文件
9.2.2 局部作用域
- 局部有效
- 作用与函数内的 代码环境,就是局部作用域。因为跟函数有关,所以也称为函数作用域
9.2.3 特殊
- 如果函数内部,变量没有声明,直接赋值。也当全局变量看。不推荐
- 代码展示:
function fn() {num = 10 // 全局变量来看 }fn() console.log(num) // 10
- 代码展示:
- 函数内部的 形参 可以看作是 局部变量
- 代码展示:
function fun(x, y) {// 形参可以看做是函数的局部变量console.log(x) // 1 } fun(1, 2) console.log(x) // x is not defined (报错)
- 代码展示:
9.3 变量的访问原则
- 只要是代码,就至少有一个作用域
- 写在函数内部的局部作用域
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
- ⚠ 访问原则(就近原则):在能够访问到到的情况下 先局部,局部没有 再找全局 (由内向外)
-
代码展示:
functin f1 () {let num = 123function f2 () {console.log(num) // 123}f2() } let num = 456 f1()
function f1() {let num = 123function f2() {let num = 0console.log(num) // 0}f2() } let num = 456 f1()
let a = 1 function fn1() {let a = 2let b = '22'function fn2() {let a = 3fn3()function f3() {let a = 4console.log(a) // a的值 = 4console.log(b) // b的值 = '22'}} } fn1()
-
9.4 匿名函数
- 没有名字的函数,无法直接使用
- 使用方式: 函数表达式 / 立即执行函数
- 1️⃣ 函数表达式:
- 函数表达式:将匿名函数赋值给一个变量,并且通过变量名称进行调用
- 语法:
let 变量名 = function () {// 函数体 }
- ⚠ 调用:变量名()
- 代码展示:
let fn = function () {console.log('我是函数表达式') } fn() // 我是函数表达式
- ⚠🔺 注意: 函数表达式 必须 先 声明 、后 调用
- 因为变量必须先声明后使用
- 2️⃣ 🔻**立即执行函数:**避免全局变量的污染(防止变量污染(冲突))
- 函数声明后立即执行,并且执行完一次后被释放
- 语法:
// 写法一: (函数)(); // 写法二: (函数 ());
- ⚠ 立即执行函数 必须 加 分号
- 立即执行函数可以传递参数
- 先写两个小括号,前面的小括号写函数
- 可以给匿名函数添加函数名
- ⚠ 最后面的小括号相当于调用函数
- 代码展示:
(function () {console.log('立即执行函数') })(); // 保存之后会在控制台立即打印 '立即执行函数'
// 第一种写法: (function () {console.log('立即执行函数第一种写法'); })();(function (x, y) { // (x, y) ---> 形参console.log(x, y); // x = 5; y = 9 })(5, 9); // (5, 9) ---> 实参// 第二种写法: (function () {console.log('立即执行函数第二种写法'); } ());(function (x, y) { // (x, y) ---> 形参console.log(x, y); // x = 5, y = 9 } (5, 9)); // (5, 9) ---> 实参
- 代码展示:
- 1️⃣ 函数表达式:
9.5 具名函数 和 匿名函数 的区别
- 具名函数:
- 可以 先调用 后声明,也可以 先声明 后调用
- 具名函数 的 调用 可以 写在 任意位置
- 匿名函数
- 函数表达式必须 先声明函数表达式 后调用
- 匿名函数 的 调用 必须写在 声明函数 的 后面
9.6 函数中的逻辑中断
- 函数的默认值
- 方案一:(赋值)
function fn(x = 0, y = 0) {x = xy = yconsole.log(x, y) } fn(1, 2) // x = 1, y = 2 fn() // x = 0, y = 0
- 方案二:(逻辑中断)(推荐)
function fn(x, y) {x = x || 0y = y || 0console.log(x, y) } fn(1, 2) // x = 1, y = 2 fn() // x = 0, y = 0
- 方案一:(赋值)
十、❗❗ 对象 - 基础
- 对象 = 属性 + 方法
10.1 对象 - object
- 对象是一种复杂数据类型
- 一种 无序 的数据集合(不可迭代)
10.2 使用对象
10.2.1 声明对象
- 语法:
- let 对象名 = {}
- let 对象名 = new Object()
let obj = {} // 声明了一个obj的对象 let obj = new Object();
- 组成:属性 + 方法
let 对象名 = {属性名: 属性值,方法名: 函数 }eg:let obj = {uname: 'pink老师',age : 18,gender: '男'}console.log(obj)// {uname: 'pink老师', age: 18, gender: '男'}
- 属性都是 成对 出现的,包括 属性名 和 属性值 ,它们之间使用英文 : 分隔
- 对象属性没有顺序
- 多个属性之间使用英文 , 分隔
- 属性就是依附在对象上的变量(外面 是 变量,对象内 是 属性)
- ⚠ 属性名可以使用 " " 或 ’ ’ ,一般情况下省略,除非名称遇到特殊符号如 空格 、 中划线 等
- ⚠ 属性名 不能 使用 反引号
10.2.2 增删查改
- 1️⃣查
- 语法:
- 对象名.属性名
- 对象名[‘属性名’] (🔺 属性名 必须 加 引号)
- ⚠ 如果属性名存放在一个 变量 里面,只能使用 数组关联语法
- 代码展示:
console.log(obj.uname) // pink老师 console.log(obj['uname']) // pink老师
- 语法:
- 2️⃣改
- 语法:对象名.属性名 = 新值
- 代码展示:
obj.gender = '女' console.log(obj.gender) // 女
- 3️⃣增
- 语法:对象名.新属性名 = 新值
obj.address = '武汉黑马' console.log(obj) // {uname: 'pink老师', age: 18, gender: '女', address: '武汉黑马'} console.log(obj.address) // 武汉黑马
- 语法:对象名.新属性名 = 新值
- 4️⃣删(了解)
- 语法:delete 对象名.属性名
delete obj.address console.log(obj) // {uname: 'pink老师', age: 18, gender: '女'}
- 语法:delete 对象名.属性名
10.2.3 对象的方法
- 方法 = 方法名 + 函数,它们之间用 : 分隔
- 多个属性 之间 使用英文 , 分隔
- 方法是依附在对象中的函数(外面 是 函数,对象内 是 方法)
- 方法名可以使用 “” 或 ‘’ ,一般情况下省略,除非遇到特殊符号如 空格、中划线 等
- 声明对象,并添加了若干方法后,可以使用,调用 对象 中的 (方法)函数,我们称之为方法调用
- 语法:对象名.方法名()
- 千万别忘了给方法名后面加 小括号
- 代码展示:
let obj = {uname: '刘德华',// 方法song: function () {console.log('冰雨')},getSum: function (x, y ) {x = x || 0y = y || 0console.log(x + y)} }// 方法调用 对象名.方法名() obj.song() // 冰雨 obj.getSum(2, 5) // 7
10.3 ❗ 遍历对象
- 1️⃣ for in 语法:
- 遍历的是 对象的属性 / 数组的索引 / 伪数组的索引 / 字符串的索引
- 得到的索引都是字符串型
for (let k in obj) {console.log(obj[k]) }
- 结论: k 是获得 对象 的属性名 , 对象名[k] 是获得 对象 的 属性值
- 遍历的是 对象的属性 / 数组的索引 / 伪数组的索引 / 字符串的索引
- 2️⃣ 判断一个成员在不在对象里面
- 语法:
属性/方法 in 对象名
- 返回值: 布尔值 (true / false)
- 代码展示:
let obj = {uname: 'jack',age: 18,gender: '男',score: 100 }; console.log('name' in obj); // true
- 语法:
- 代码展示:
//声明一个 obj 对象 let obj = {uname: 'pink老师',age: 18,gender: '男' }// 用 fou in 循环遍历对象 for (let k in obj) { // k 可以是任何变量,选择 k/key 是因为许多程序员都在使用// console.log(k) // k 是字符串型的,带有引号// k => 'uname' 'age' 'gender'// obj 对象里面没有 'uname'、 'age'、 'gender' 的属性名 ------ 有引号// obj 对象里面的属性名是 uname、 age、 gender ------ 没有引号// 查询对象里面的属性有两种方法:1)对象名.属性名// 2)对象名['属性名']// 原因:obj[k] === obj['uname'] === obj.uname// obj[k] === obj['age'] === obj.age// obj[k] === obj['gender'] === obj.gender// 所以,利用for in循环遍历对象采用第二种查询方法// 结论:k 是获得对象的属性名 , 对象名[k] 是获得 属性值console.log(obj[k]) // 'pink老师'(string) 18(number) '男'(string) }
- 渲染学生信息
- 代码展示:
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>table {width: 600px;text-align: center;}table,th,td {border: 1px solid #ccc;border-collapse: collapse;}caption {font-size: 18px;margin-bottom: 10px;font-weight: 700;}tr {height: 40px;cursor: pointer;}table tr:nth-child(1) {background-color: #ddd;}table tr:not(:first-child):hover {background-color: #eee;}</style> </head><body><h2>学生信息</h2><p>将数据渲染到页面中...</p><table><caption>学生列表</caption><tr><th>序号</th><th>姓名</th><th>年龄</th><th>性别</th><th>家乡</th></tr><script>// 1.数据准备let students = [{ name: '小明', age: 18, gender: '男', hometown: '河北省' },{ name: '小红', age: 19, gender: '女', hometown: '河南省' },{ name: '小刚', age: 17, gender: '男', hometown: '山西省' },{ name: '小丽', age: 18, gender: '女', hometown: '山东省' }]// 2.开始渲染页面for (let i = 0; i < students.length; i++) {document.write(`<tr><td>${i + 1}</td><td>${students[i].name}</td><td>${students[i].age}</td><td>${students[i].gender}</td><td>${students[i].hometown}</td></tr>`)}</script></table></body></html>
- 代码展示:
10.4 内置对象
10.4.1 Math对象包含的方法
- 1️⃣Math.random():生成0-1之间的随机小数(🔺包含0不包括1)
- 如何生成0-10的随机小数?
-
let num = Math.floor(Math.random() * (10 + 1))
-
- 如何生成5-10的随机数?
-
let num = Math.floor((Math.random() * (5 + 1)) + 5
-
- 如何生成N~M的随机数?
-
let num = Math.floor(Math.random() * (M - N + 1)) + N function getRandom (N, M) {// return Math.floor(Math.random() * (M - N + 1)) + N;return parseInt(Math.random() * (M - N + 1)) + N; }
-
- 数组随机数:
Math.floor(Math.random() * arr.length)
- 如何生成0-10的随机小数?
- 2️⃣Math.ceil(数据):向上取整
- 代码展示:
console.log(Math.ceil(1.1)) // 2 console.log(Math.ceil(1.01)) // 2
- 代码展示:
- 3️⃣Math.floor(数据):向下取整
- 代码展示:
console.log(Math.floor(1.9)) // 1 console.log(Math.floor(1.99)) // 1
- 代码展示:
- 4️⃣Math.max(数据):找最大数
- 代码展示:
console.log(Math.max(0.1, 1, 65, 23, 88)) // 88
- 代码展示:
- 5️⃣Math.min(数据):找最小数
- 代码展示:
console.log(Math.min(99, 65, 3, 0.1, -99)) // -99
- 代码展示:
- 6️⃣pow:幂运算(了解)
- 7️⃣Math.abs(数据):绝对值
- 代码展示:
console.log(Math.abs(-100)) // 100
- 代码展示:
- 8️⃣Math.round(数据):四舍五入(取整数)
- 代码展示:
console.log(Math.round(2.45)) // 2 console.log(Math.round(2.5)) // 3 console.log(Math.round(-20.5)) // -20 console.log(Math.round(-20.51)) // -21
- 代码展示:
贰、❗❗ Web APIS
- Web API:是一套操作网页内容(DOM)与浏览器窗口(BOM)的对象
- API:就是一些预定义好的方法,这些方法可以实现特定的功能,开发人员可以直接使用
- Web API:浏览器提供了一套操作网页和浏览器的方法,通过这些方法可以轻松的操作元素和浏览器
- 复杂数据类型 用 const 声明:复杂数据类型 放在 堆 里面,栈里面存放的地址指向堆里面存放的数据,变的只是堆里面存放的数据,存放数据的地址没有发生变化
- 变量名 -> 栈地址-> 堆数据
-
const实际上指的并不是变量的值不得改动, 其实说的是变量指向的那个内存空间中保存的数据不得改变 简单数据类型是将值保存在栈中,所以用const声明简单数据类型时,值不得改变,相当于常量 而复杂数据类型是将引用地址保存在栈中,具体的值保存在堆中 那么用const声明复杂数据类型时,比如对象,数组时,只能保证的是这个地址是固定不变的 堆中保存的数据是不是可变的,就无法保证了
一、❗❗ DOM(文档对象模型)
- Document Object Model — 文档对象模型
- 定义:是HTML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以在从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将 web 页面和程序语言连接起来。进而操作网页的内容,实现各种功能和部分特效。
1.1 DOM树 和 DOM对象
1.1.1 DOM树
- DOM树:一种树状结构,把页面标签按照树状结构排列好,结构更加清晰
- 每个DOM对象中都有表示层级关系的属性,利用这些属性把所有的DOM对象联系在一起,就形成一个树状结构,称为DOM树
- 作用:文档树直观的 体现了 标签与标签 之间 的 关系
1.1.2 DOM对象
- **DOM对象:**浏览器根据htm标签自动生成的JS对象
- 浏览器把网页内容翻译成一个个的对象,把 网页内容 的 特征 翻译成 对象 的属性
- document对象:是DOM里提供的一个对象(DOM里面最大的对象)
- 它提供的属性和方法都是 用来访问 和 操作 网页内容的
1.2 获取DOM对象
- 打印对象:打印元素的时候,以对象的形式展现
console.dir(对象);
1.2.1 ❗❗ 根据CSS选择器来获取DOM元素
- 1️⃣ 选择匹配的 第一个 元素
- 语法:
document.querySelector('css选择器')
- 代码展示:
const li = document.querySelector('ul li')
- 参数:小括号里面 包含 一个 或 多个 有效的css选择器 字符串(引号)
- 返回值:
- css选择器 匹配的 第一个元素,一个 HTMLElement 对象
- ⚠ 如果 没有匹配 到元素就是 null
- ⚠ 注意:必须加引号
- 语法:
- 2️⃣ 选择匹配的 多个 元素
- 语法:
document.querySelectorAll('css选择器')
- 代码展示:
const lis = document.querySelectorAll('li') //NodeList[li, li, li]
- 参数:小括号里面 包含 一个 或 多个 有效的CSS选择器 字符串
- 返回值:
- CSS选择器匹配的 NodeList 对象集合
- 如果页面 不存在 这个 元素,得到的就是一个 空的伪数组
- 把 所有 匹配的 元素 放到 NodeList🟨伪数组🟨 里面 返回
- 有长度,有索引
- 没有push(),pop()等数组方法
- 想要得到里面的每一个对象,则需要遍历获得
- 语法:
1.2.2 获取HTML、body、head、title
document.documentElement --- html
document.body --- body
document.head --- head
document.title --- title
1.2.3 ❌其他获取元素的方式
- 1️⃣根据 id 获取元素
-
document.getElementById('id名称')
- 注意:
- id名称不加 #
-
- 2️⃣根据 标签 获取 一类 元素
-
document.getElementsByTagName('标签名称')
- 注意:
- getElementsByTagName
- 返回值:伪数组
-
- 3️⃣根据 类名 获取元素
-
document.getElementsByClassName('类名')
- 注意:
- 类名不加 .
- getElementsByClassName
- 返回值:伪数组
-
1.3 操作元素内容
1.3.1 对象.innerText 属性
- 将 元素 文本内容 添加/更新 到 任意标签 位置
- 显示 纯文本,不解析标签
- 见代码展示
1.3.2 对象.innerHTML 属性
- 将 元素内容 添加/更新 到任意标签位置
- 包括标签、文本、注释
- 会解析标签,多标签建议使用模板字符串
- ⚠ 既要保留原来内容又要添加新内容,采用 字符串拼接 的方式
-
innerHTML += '要添加的文本'
-
- 见代码展示
代码展示:
<div class="box"> 天地不仁以万物为刍狗!!! </div>
<strong>const box = document.querySelector('.box') // 对象.innerText 属性box.innerText = '扶我起来,我还能干!!!'box.innerText = '<strong>扶我起来,我还能干!!!</strong>'// 对象.innerHTML 属性box.innerHTML = '扶我起来,我还能干!!!'box.innerHTML = '<strong>扶我起来,我还能干!!!</strong>'
</strong>
- ⚠innerText 和 innerHTML 的区别
- innerText
- 只能 获取 元素文本,无法 获取 标签
- ⚠ 在获取文本的时候,包含 子元素 的 文本
- innerHTML
- 可以 获取对象里面的所有 文本+标签
- 代码展示:
<body><div>123<p>456<span>789</span></p></div><script>console.log(document.querySelector('div').innerText);console.log(document.querySelector('div').innerHTML);</script> </body>
- innerText
1.3.3 获取表单元素文本
- 语法: 元素.value
- 获取 输入的字符长度 :元素.value.length
- ⚠ 获取 button 的文本依然使用 innerHTML(button双标签)
- 拓展:
- ⚠ 元素.value.trim() - 去除字符串 左右两侧 的空格
1.4 操作元素属性
1.4.1 操作 元素 属性
- 语法:元素.属性 = ‘值’
- 代码展示:
<img src="./images/1.webp" alt=""> //随机数函数 function getRandom(N, M) {return Math.floor(Math.random() * (M- N + 1)) + N } //获取图片对象 //img在html中是标签,在js中是对象 const pic = document.querySelector('img') // 修改对象的属性值 pic.src = `./images/${getRandom(1, 6) }.webp`
- 代码展示:
1.4.2 控制 样式 属性
- 1️⃣ 通过 style属性 操作css
- 语法:元素.style.样式属性 = ‘值’
- 对于复杂的样式属性建议使用 小驼峰 命名法
- 生成的是 行内样式表,权重很高,只有 !important 能做掉它
- ⚠🔺 只写 属性
- 代码展示:
// 获取对象(元素) const box = document.querySelector('div') // 修改样式属性 对象.style.样式属性 = '值' box.style.width = '400px' box.style.height = '100px' box.style.backgroundColor = 'red' box.style['background-color'] = 'green'
- 语法:元素.style.样式属性 = ‘值’
- 2️⃣ 通过 类名(className) 操作css
- 语法:元素.className = ‘类名’
- ⚠ 注意:会覆盖前面的类名 新值换旧值
- 想要原来的类名 -> 元素.className = ‘旧类名 新类名’
- 代码展示:
<style>div {width: 200px;height: 200px;background-color: pink;}.active {width: 300px;height: 300px;background-color: hotpink;margin-left: 100px;} </style><body><div class="one"></div><script>// 1.获取元素// let box = document.querySelector('css选择器')let box = document.querySelector('div')// 2 给div添加类名 class 是个关键字,选用className替代它// 新值换旧值,会覆盖原来的类名box.className = 'active'// 用旧类名+新类名的形式覆盖原来的类名box.className = 'one active'</script> </body>
- 语法:元素.className = ‘类名’
- ❗3️⃣ 通过 classList 操作类 控制css
- 语法:
- 追加 类:元素.classList.add(‘类名’)
- 删除 类:元素.classList.remove(‘类名’)
- 切换 类:元素.classList.toggle(‘类名’)
- 如果有这个类名就是删掉,没有就追加
- 替换 类:元素.classList.replace(‘旧类名’, ‘新类名’)
- 两个参数,第一个是原来的类名,第二个参数是替换的类名
- 是否包含指定的 类:元素.classList.contains(‘类名’)
- 判断是否包含指定的类名,返回值是布尔值 true / false
- ⚠ 注意:
- 类名 不加 点,并且 是 字符串
- 是 方法,注意加小括号
- 代码展示:
// 获取对象 const box = document.querySelector('.one')// 追加类名 box.classList.add('two') box.classList.add('three')// 删除类名 box.classList.remove('three')// 切换类名 // 如果有这个类名就是删除,没有就是追加 box.classList.toggle('ab') box.classList.toggle('one')// 替换类名 // 将 旧类名box 替换成 新类名box1 box.classList.replace('box', 'box1')// 判断是否包含指定的类名 console.log(box.classList.contains('box')) // true
- 语法:
- classList 和 className区别
- classList 是 追加类名,将新类名追加到旧类名后面,不影响以前的类名
- className 是 覆盖类名,新类名 覆盖 旧类名,影响以前的类名
1.4.3❗❗ 操作 表单元素 属性
- 语法:
- 获取:元素.属性名
- 设置:元素.属性名 = 新值
- 代码展示:获取表单里面的值
const input = document.querySelector('.computer') console.log(input.value) input.value = '扶我起来,我还能干!!!'
- ⚠ 注意:对象.innerHTML 只能获取 普通元素 的 文本,获取 表单元素 的 文本 需要使用 对象.value
- ⚠ 注意: 对象.value 获得的文本是 包含 首尾 的 空白符
- 想要获得 有效的文本 需要使用 trim() 方法[对象.value.trim()],删除首尾的空白符
- ⚠注意:获取 button 的文本还是用 innerHTML
- ⚠ 注意: 对象.value 获得的文本是 包含 首尾 的 空白符
- 表单属性中添加就有效果,移除就没有效果,一律使用 布尔值 表示,如果为 true 代表 添加 了该 属性 ,如果是 false 代表 移除 该 属性
- disabled(禁用)、checked(选中)
- 除了 ’ ', false, 0, null, undefined,NaN 其余的都是true,但是不建议写,建议写布尔值
- 代码展示:
<input type="checkbox" value="" name=""> const input = document.querySelector('.computer') input.checked = true // 让复选框选中 input.checked = false // 让复选框不选中 input.disable = true // 禁用吗? - 禁用(true) input.disable = false // 禁用吗? - 不禁用(false默认值)
1.4.4 ❗❗ 自定义属性
- 属性
- 标准属性:标签天生自带的属性,可以直接使用 点语法 操作
- 自定义属性:
- 在h5中推出了专门的 data- 自定义属性
- 在标签上一律以 data- 开头(必须以 data- 开头)
- 在DOM对象上一律以 dataset 对象方式获取
- dataset 是一个 自定义属性集合,包含 该标签内 的 所有 自定义属性
- 代码展示:
<div data-id="1" data-spm="不知道">1</div> <div data-id="2">2</div> <div data-id="3">3</div> <div data-id="4">4</div> <div data-id="5">5</div> <script>// 获取元素const one = document.querySelector('div')// one是一个HtmlElement对象console.log(one)// dataset是一个对象集合console.log(one.dataset)// 获取dataset对象里面的id属性console.log(one.dataset.id)// 获取dataset对象里面的spm属性console.log(one.dataset.spm) </script>
- ❌⛔ 拓展:
- 获取自己 瞎定义的属性
- 浏览器不会识别 瞎定义属性,并且它不会体现在DOM对象上
- 语法:
DOM对象.getAttribute(瞎定义属性名)
1.5 ❗❗ 定时器 - 间歇函数
- 定时器 = setInterval() + setTimeout()
- setInterval(函数, 间隔时间)(间歇函数):按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到clearInterval()被调用或窗口关闭
- 间歇函数可以根据时间自动重复执行某些代码
- setTimeout(函数, 延迟时间)(延时函数):在指定的毫秒数后调用函数或计算表达式 (Timeout - 超出)
- 定时器 里面的 第一个参数 是 回调函数
- 将一个函数作为参数传递给另外一个函数,这个函数就是回调函数
1.5.1 开启定时器
- 语法:
匿名函数:setInterval(函数, 间隔时间) // Interval - 间隔,间隙 具名函数:setInterval(函数名, 间隔时间)
- 作用:每隔一段时间 回头调用函数(先隔段时间 ,再调用函数)
- 间隔时间 单位 是 毫秒(ms),不用写
- 不是立即调用函数,时间间隔 过后再去 调用函数
- 间歇函数返回值
- 表示 当前定时器 是 页面中 的 第几个 定时器,是一个 id数字(数字型)(唯一的)
- 一个 间歇函数 只有 一个 返回值,并且是唯一
- 代码展示:
// 匿名函数 setInterval(() => {console.log('扶我起来,我还能干!!!') }, 1000)// 具名函数 function fn() {console.log('扶我起来,我还能干!!!') } setInterval(fn, 1000) // fn() --- 执行这个函数,只执行一次 (fn()调用这个函数) // fn --- 每隔一段时间,回头去找fn这个函数(自动调用),再执行(fn是一个变量,代表这个函数)// 定时器的返回值,是数字型,是id // 声明一个变量,接收定时器的返回值 let n = setInterval(() => {console.log(1) }, 1000) console.log(n) // 1function fn() {console.log('扶我起来,我还能干!!!') } let m = setInterval(fn, 1000) console.log(m) // 2
1.5.2 关闭定时器
- 语法:
// 匿名函数 let 变量名 = setInterval(函数, 时间间隔) // 具名函数 let 变量名 = setInterval(函数名, 时间间隔) clearInterval(变量)
- 代码展示:
// 匿名函数 let n = setInterval(() => {console.log(11) }, 1000)// 具名函数 function fn() {console.log('扶我起来,我还能干!!!') } let m = setInterval(fn, 1000)// 关闭定时器 clearInterval(n) clearInterval(m)
二、❗❗ DOM事件基础
2.1 事件监听(绑定)
- 让程序检测是否有事件产生,一旦事件触发,就立即调用一个函数做出响应,也称为 绑定事件 / 注册事件
- 事件监听三要素:
- 事件源
- 事件类型
- 事件调用的函数(事件处理函数)
- 语法:
元素对象.addEventListener('事件类型', 要执行的函数)
- ⚠ 注意:事件类型 要加 引号
- L2 注册的 事件 不会 出现 覆盖
- L0 注册的事件会发生覆盖(后面的覆盖前面的)(同对象、同事件类型)
- 代码展示:
// 获取元素 const btn = document.querySelector('button') // 事件监听-点击事件 btn.addEventListener('click', () => {alert('扶我起来,我还能干!!!') })
2.2 事件类型
2.2.1 鼠标事件
- 1️⃣ click - 鼠标点击
- 2️⃣ mouseenter - 鼠标经过
- 3️⃣ mouseleave - 鼠标离开
- 4️⃣ mousemove - 鼠标移动
- 5️⃣ dblclick - 鼠标左键双击
2.2.2 焦点事件
- 1️⃣ focus - 获得焦点
- 2️⃣ blur - 失去焦点
2.2.3 键盘事件
- 1️⃣ keydown - 键盘按下触发
- 2️⃣ keyup - 键盘抬起触发
- 注意: 用鼠标粘贴内容不会触发
2.2.4 文本事件
- 1️⃣ input - 用户输入事件
- 获取用户 输入文本 :对象.value
- 获取用户 输入文本 的 长度 :对象.value.length
- ⚠ 注意:
- 得到的 是 数字型
- ⚠ 包括 左右两侧 的 空格
- ⚠ 注意:
- 想要获得 有效 的 文本和长度 (不包括首尾的空白符)
- 有效文本: 对象.value.trim()
- 有效长度: 对象.value.trim().length
- trim() 方法:删除 字符串 首尾 空白符(空格、制表符、换行符等其他空白符)
- 不会 改变 原始字符串
- 不适用于null,undefined,Number类型
2.2.5 表单事件
- 1️⃣ submit - 提交事件
- 2️⃣ change - 失去焦点并且表单内容发生改变触发事件
- 3️⃣ 重置表单: form.reset()
2.2.6 光标的坐标
- 1️⃣ clientX 和 clientY
- 光标距相对于 浏览器 可视化窗口 左上角 的位置
- 鼠标在窗口中的位置
- 2️⃣ pageX 和 pageY
- 光标距离 文档流 左上角 的位置
- 鼠标在页面中的坐标
- 计算鼠标在某个盒子中的坐标:
- 鼠标到盒子顶部的距离 = 鼠标到页面顶部的距离 - 盒子顶部到页面顶部的距离
- 鼠标到盒子左侧的距离 = 鼠标到页面左侧的距离 - 盒子左侧到页面左侧的距离
-
- 3️⃣ offsetX 和 offsetY
- 光标距离 DOM元素 左上角 的位置
- 鼠标在标签中的位置
- ⚠🔺 拓展:利用 js 调用 事件
- 语法:元素.事件类型()
2.3 事件对象 - event
- 也是个对象,里面有事件触发时相关的信息
2.3.1 获取事件对象
- ⚠ 使用场景:
- 可以判断用户按下哪个键
- 可以判断鼠标点击了哪个元素,从而做相应的操作
- 语法:
- 在 事件绑定 的 回调函数 的 第一个参数 就是 事件对象
- 一般命名为 event、ev、e
-
element.addEventListener('事件类型', function (e) {})
- 在触发 DOM 上的某个事件时,会产生一个事件对象
- event对象 包含与创建它的特定相关的和方法
2.3.2 事件对象常用属性
- type:获取 当前的 事件类型
- clientX / clientY:获取 光标 相对于 浏览器可视化窗口 左上角 的位置
- offsetX / offsetY:获取 光标 相对于 当前DOM元素 左上角 的位置
- pageX / pageY : 光标距离 文档流 左上角 的位置
- key:
- 用户 按下 键盘键的值
- 现在不提倡使用keyCode
- 代码展示:
元素.addEventListener('click', function (e) {console.log(e.key)console.log(e.type) })
2.4 环境对象
- 函数内部特殊的变量 this,代表当前函数运行时所处的环境
- 每个函0数 里面 都有 this
- 非严格模式
- this指向函数的调用者(普通函数里面 this -> window)
- 事件侦听里面,指向事件源
- 箭头函数没有this(箭头函数不会自己创建this,它只会沿用自己所在这条作用域链的上层作用域的this)
- 定时器里面this指向window
2.5 回调函数
- 官方:如果将函数A作为参数传递给函数B时,我们称函数A为 回调函数
- 把一个 函数 当作 参数 来 传递给 另外一个函数 的时候,这个函数就是 回调函数
三、❗❗ DOM事件进阶
3.1 事件流
3.1.1 事件流与两个阶段说明
- 事件流 = 事件捕获 + 事件目标 + 事件冒泡
- 事件流指的是:事件 完整执行过程 中的 流动路径
- 过程:事件捕获 => 事件目标阶段 => 事件冒泡 整个完整的过程就是事件流
- 两个阶段:
- 捕获阶段:从父到子(从大到小)
- 冒泡阶段:从子到父(从小到大)
- 实际工作中都是使用 事件冒泡 为主
-
3.1.2 ❌ 事件捕获(了解)
- 概念:从DOM的 根元素 开始去执行对应的事件(从外到里)
- 事件捕获需要写对应代码才能看见效果
- 代码:
DOM.addEventListener(事件类型, 事件处理函数[, 是否使用捕获机制 = false])
- addEventListener第三个参数传入 true 代表是捕获阶段触发(很少使用)
- 若传入false代表冒泡阶段触发,默认就是false
- 若是用 L0(on事件类型) 事件监听,则只有冒泡阶段,没有捕获
- 代码:
3.1.3 事件冒泡
- 从子到父(从小到大)
- 概念:当一个元素触发事件后,会 依次 向上 调用 所有父级元素 的 同名事件(同种事件类型)
- 事件冒泡是默认存在的
- 事件冒泡的必要性
- 如果没有冒泡,给大盒子注册点击事件,点击的是里面的小盒子,会导致大盒子的点击无法执行
- 事件委托(委托给祖先元素)
- L2事件监听第三个参数是false,或者默认都是冒泡
- 代码展示:
const fa = document.querySelector('.father') const son = document.querySelector('.son') document.addEventListener('click', function () {alert('我是爷爷') }) fa.addEventListener('click', function () {alert('我是爸爸') }) son.addEventListener('click', function () {alert('我是儿子') }) // 事件冒泡:从子到父 // 弹出框的顺序依次是:儿子 -> 我是爸爸 -> 我是爷爷
3.1.4 阻止冒泡
- 语法:
事件对象.stopPropagation() // 方法 停止传播 sp(快捷) e.stopPropagation() // 事件对象 - 回调函数的第一个参数
- 此方法可以阻断事件流动传播 ,不光在冒泡阶段有效,捕获阶段也有效
- 代码展示:
const fa = document.querySelector('.father') const son = document.querySelector('.son') document.addEventListener('click', function () {alert('我是爷爷') }) fa.addEventListener('click', function () {alert('我是爸爸') }) son.addEventListener('click', function (e) {alert('我是儿子')// 阻止流动传播(阻止事件冒泡)// 在这一块卡住,不允许向上传播e.stopPropagation() }) // 弹出框:我是儿子
- 阻止元素默认行为:
- 语法:
e.preventDefault() // 方法 阻止默认 pd(快捷) // 阻止 链接跳转 // 阻止 表单提交(缺点:提交数据页面h)
- 代码展示:
<body><form action="http://www.itcast.cn"><input type="submit" value="免费注册"></form><a href="http://www.baidu.com">百度一下</a><script>// 获取元素const a = document.querySelector('a')const form = document.querySelector('form')// 事件侦听-a-点击事件a.addEventListener('click', function (e) {// 阻止a的默认行为-页面跳转e.preventDefault()})// 事件侦听-form-提交事件form.addEventListener('submit', function (e) {// 阻止form的默认行为-表单的提交e.preventDefault()})</script> </body>
- 语法:
3.1.5 两种鼠标事件的区别
- ⚠ 注意:
- mouseover 和 mouseout 会 有 冒泡效果
- mouseenter 和 mouseleave 没有 冒泡效果(推荐)
3.1.6 解绑事件
- 1️⃣ L0事件解绑(on方式)
- 直接使用 null 覆盖就可以实现事件的解绑
- 代码展示:
btn.onclick = function () {alert('点击了') } // L0事件移除解绑 btn.onclick = null
- 2️⃣ L2 事件解绑
-
语法:
removeEventListener(事件类型, 函数名[, 获取捕获或冒泡阶段])
- ⚠ 中括号包裹的参数可以省略
- ⚠🔺 匿名函数 无法进行 事件解绑 操作
- ⚠ 解绑的时候必须是 同一个函数(两个函数体一样 的 匿名函数 不是 同一个函数)
-
代码展示:
<script>// 获取元素const btn = document.querySelector('button')// 声明函数let fn = function (e) {alert(`事件解绑语法:元素.removeEventListener(事件类型, 函数名)匿名函数 无法进行 事件解绑 操作${e.target.tagName}`)}// 事件侦听-点击事件btn.addEventListener('click', fn)// 事件解绑btn.removeEventListener('click', fn) </script>
-
3.1.7 两种注册事件的区别
- 1️⃣ 传统on 注册(L0)
- 同一个对象,后面注册的事件会 覆盖 前面注册的事件(同一个事件)
- 直接使用 null 覆盖就可以实现事件的解绑
- 都是 冒泡阶段 执行的(只有冒泡没有捕获)
- 2️⃣ 事件监听 注册(L2)
- 语法:addEventListener(事件类型, 事件处理函数[ , 是否使用捕获 = false])
- 既能捕获也能冒泡
- 捕获 将第三个参数 改成 true
- 冒泡不用写,默认就是冒泡(false)
- 后面注册的事件 不会覆盖 前面注册的事件(同一个事件)
- 可以通过 第三个参数 去确定是在 冒泡阶段 或者 捕获阶段 执行的
- 必须使用 removeEventListener(事件类型, 事件处理函数[ , 获取捕获或者冒泡阶段])
- ⚠🔺 匿名函数无法解绑
- 语法:addEventListener(事件类型, 事件处理函数[ , 是否使用捕获 = false])
3.2 事件委托
- 优点:
- 减少注册次数
- 提高程序性能
- ⚠ 为未来元素预备事件(添加节点)
- 原理: 事件委托其实是利用 事件冒泡 的特点
- 给 父元素 注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件
- ⚠ 注意: 事件触发元素嵌套关系很复杂就不可以使用事件委托
- 实现:
- 获得 真正 触发事件 的 元素(对象):事件对象.target
- 获得 真正 触发事件元素 的 标签名称:事件对象.target.tagName
- 代码展示:
<body><ul><li>第1个孩子</li><li>第2个孩子</li><li>第3个孩子</li><li>第4个孩子</li><li>第5个孩子</li><p>我不需要变色</p></ul><script>// 1.点击每个小li,当前li文字变色// 按照事件委托的方式,委托给父级,事件写到父级身上// 获取元素const ul = document.querySelector('ul')// 事件绑定ul.addEventListener('click', function (e) {// e:事件对象// 得到一个事件对象// console.log(e)// 得到被点击的元素// console.log(e.target)// 得到被点击元素的标签名称// 得到的标签名称是 大写的 字符串// console.log(e.target.tagName) // 'LI'// 判断点击的是不是li,如果是li文字就变颜色if (e.target.tagName === 'LI') {e.target.style.color = 'red'}})</script> </body>
3.3 其他事件
3.3.1 页面加载事件
- ⚠ JavaScript 写在body上面,必须 使用 load事件 或者 DOMContentLoaded事件
- 1️⃣ load 事件
- 等待页面 所有外部资源(外联CSS、外联JavaScript,图片……) 加载完毕 时,就回去执行回调函数
- 事件名: load(等待)
- 监听 整个页面 所有外部资源 加载完毕
- ⚠ 给 window 添加 load 事件
- 语法:
window.addEventListener('load', function () {// 执行操作 })
- 代码展示:script标签在body标签上方
<script>// 给 window 添加 页面加载事件(load)window.addEventListener('load', function () {// 获取元素const btn = document.querySelector('button')// 事件侦听-点击事件btn.addEventListener('click', function () {alert(`页面加载事件给 window 添加 load 事件window.addEventListener('load', function() {})`)}) }) </script> <body><button>点击</button> </body>
- ⚠ 注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定 load事件
- 2️⃣ DOMContentLoaded 事件
- 当 初始的HTML文档(DOM节点) 被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待外部资源加载
- 事件名: DOMContentLoaded
- 监听页面 DOM节点 加载完毕
- ⚠ 给 document 添加 DOMContentLoaded 事件
- 语法:
document.addEventListener('DOMContentLoaded', function () {// 执行的操作 })
- 代码展示:
document.addEventListener('DOMContentLoaded', function () {// 获取元素const btn = document.querySelector('button')// 事件侦听-点击事件btn.addEventListener('click', function () {alert(`页面加载事件给 document 添加 DOMContentLoaded 事件document.addEventListener('DOMContentLoaded', function() {})`)}) })
3.3.2 元素滚动事件 - scroll
- 滚动条 滚动的时候 触发(⚠ 页面 必须有 滚动条 才能 触发)
- 让 页面 具有 滑动效果 (不是瞬间到指定位置,而是缓慢滑动到指定位置)
-
/* 页面滑动 */ html {/* 让滚动条丝滑的滑动 *//* 滚动-行为:平滑 */scroll-behavior: smooth; }
-
- 让 页面 具有 滑动效果 (不是瞬间到指定位置,而是缓慢滑动到指定位置)
- 让 html标签(页面最大的标签) 滚动
-
document.documentElement.scrollTop // html被卷去的高度 window.pageYoffset // 页面滚出去的高度(页面在竖轴的偏移量) document.documentElement.scrollTop === window.pageYoffset
-
- 应用场景:固定导航栏、返回顶部
- 事件名: scroll
- 监听 整个页面 滚动
- 语法:
window.addEventListener('scroll', function () {// 执行的操作 })
- ⚠ 注意:
- 给 window(常用) 或 document 添加 scroll 事件
- 监听 某个元素的内部 滚动 直接给 某个元素 加即可
- 代码展示:
- 语法:
- 获取位置
- scrollTop(被卷去的头部) 和 scrollLeft(被卷去的左侧) (属性)
- ⚠🔺 读写属性(可以 读取 亦可以 赋值)
- ⚠ 获取到的是 数字,赋值的时候 不带单位
- 检测页面滚动的头部距离
-
document.documentElement.scrollTop = 数字
-
window.pageYoffset - 只读属性
-
- 获取 被卷去 的大小
- 获取 元素内容 往左、往上滚出去 看不到 的 距离
- ⚠ 得到的是:数字型 不带单位
- 尽量写在 scroll事件 里面
- 代码展示:
<style>* {margin: 0;padding: 0;box-sizing: border-box;}body {height: 3000px;}div {display: none;margin: 100px auto;width: 470px;height: 150px;border: 1px solid #000;text-align: center;font-size: 20px;font-family: '隶书';}.active {display: block;position: fixed;top: 0;left: 50%;transform: translateX(-50%);margin-top: 0;} </style><body><div>世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!</div><script>// 事件侦听-页面滚动事件-windowwindow.addEventListener('scroll', function () {// 获取html元素const html = document.documentElement// 获取div元素const div = document.querySelector('div')// console.log(html.scrollTop); // 得到的是数字型// scrollTop >= 300显示div并固定在可视区域顶部,小于300隐藏if (html.scrollTop >= 300) {div.classList.add('active')} else {div.classList.remove('active')}})</script> </body>
- 让页面 滚动到指定位置
- 1️⃣ 属性赋值
document.documentElement.scrollTop = 指定位置距离顶部的距离
- 2️⃣ 方法
window.scrollTo(x, y)
- 1️⃣ 属性赋值
- scrollTop(被卷去的头部) 和 scrollLeft(被卷去的左侧) (属性)
3.3.3 ❌ 页面尺寸事件 - resize(了解)
- 窗口尺寸改变 的时候 触发事件
- 事件类型: resize
- 语法:
window.addEventListener('resize', function () {// 执行的代码 })
- 检测屏幕宽度
- 语法:
window.addEventListener('resize', function () {let w = document.documentElement.clientWidthconsole.log(w) })
- 语法:
- 获取元素宽高 (属性)
- 获取元素的 可见部分 宽高(不包含border、margin、滚动条)
- clientWidth 和 clientHeight
- 得到的是 数字型
-
3.4 ❗❗ 元素的尺寸和位置
- 1️⃣ 获取 宽高:(属性)
- 获取元素 自身的宽高
- 内容 + padding + border
- offsetWidth 和 offsetHeight
- 获取到的是 数值
- ⚠ 获取的是 可视宽高,如果盒子是隐藏的,获取的结果是0
- 获取元素 自身的宽高
- 2️⃣ 🔻 获取 位置:
- ① 获取元素 距离自己 最近一级 定位 祖先元素 的 左、上 距离
- 带有 定位属性 的 祖先元素
- 如果都没有,就以文档左上角为准
- offsetLeft 和 offsetTop
- 相对于 页面 来说
- ⚠ 只读属性
- 获取的是可视宽高,若盒子隐藏,则获得的是0
- ② ❌ 元素.getBoundingClientRect() (了解)
- 返回元素的 大小 及其 相对于视口的位置
- 相对于 视口
- 代码展示:
const div = document.querySelector('div') div.getBoundingClientRect()
- ① 获取元素 距离自己 最近一级 定位 祖先元素 的 左、上 距离
✅ 总结
属性 | 作用 | 说明 |
---|---|---|
scrollLeft 和 scrollTop | 被 卷去 的 头部 和 左侧 | 配合 页面滚动(scroll 事件) 来用,可读写 |
clientWidth 和 clientHeight | 获得 元素 的 宽度 和 高度 | 不包含border、margin、滚动条,用于js 获取元素大小 只读属性 |
offsetWidth 和 offsetHeight | 获得 元素 的 宽度 和 高度 | 包含border、padding、滚动条等,只读属性 |
offsetLeft 和 offsetTop | 获取元素距离 自己定位父元素 的左、上距离 | 获取 元素位置 的时候使用,只读属性 |
- scroll系列 、 client系列 、 offset系列
- scroll系列: 标签内部 内容 的大小,位置
- scrollTop / scrollLeft:表示标签真实内容相对于标签的位置
- ❌scrollWidth / scrollHeight:表示标签真实内容的大小(和标签本身的大小无关,是内容的宽高)
- client系列: 标签 容纳范围(border里面) 的大小、位置
- clientWidth / clientHeight:表示标签内容区域的大小
- ❌clientTop / clientLeft:表示标签内容区域的位置(几乎不用,仅仅表示上边框的高度,左边框的宽度)
- ✔🔻 offset系列: 标签本身 的大小、位置
- offsetWidth / offsetHeight:包含content + padding + border
- offsetTop / offsetLeft:最近一级 的 带有定位属性 的 祖先元素 的 相对位置(如果没有定位,那么就是相对于body)
- scroll系列: 标签内部 内容 的大小,位置
- 拓展:
- 添加css让页面滚动平滑
-
html {scroll-behavior: smooth; }
-
- if单分支语句拓展:
-
if (old) old.classList.remove('active')
-
old && old.classList.remove('active') - 逻辑与
-
old?.classList.remove('active') - 可选链
-
- 属性选择器
-
document.querySelector('[data-name=new]') 自定义属性 的 属性值 可以 省略 双引号(不推荐)
-
- 添加css让页面滚动平滑
四、❗❗ 日期对象
- 用来 表示时间 的 对象
- 作用: 得到 当前系统 的 时间
- 日期对象:Date构造函数的实例,记录了一个时间信息
4.1 实例化
- 实例化:有 new 关键字的都是实例化(见 JS 高级)
4.1.1 得到当前时间
- 创建一个 时间对象 并 获取时间
- 语法:
const 常量名 = new Date()
- 代码展示:
const date = new Date() console.log(date) // Wed Aug 03 2022 20:37:52 GMT+0800 (中国标准时间) // 周三 八月 3号 年份 时间
- 语法:
4.1.2 指定时间
- 倒计时 的时候 使用
- 语法:
const 常量名 = new Date('指定的时间')
- ⚠ 参数:
- 数字 : 月份是从 0 开始的
- 字符串 : 月份是正常的
- 代码展示:
const date = new Date('2022-8-3 20:50:00') let h = date.getHours() console.log(h) // number console.log(date) console.log(typeof date) // object // Wed Aug 03 2022 20:50:00 GMT+0800 (中国标准时间)
4.2 日期对象方法
-
语法 作用 说明 对象.getFullYear() 获得 年份 获取 四位 年份 对象.getMonth() 获得 月份 取值为 0 ~ 11 对象.getDate() 获取 月份中的 某一天 不同月份取值不同 对象.getDay() 获取 星期 取值为 0 ~ 6 对象.getHours() 获取 小时 取值为 0 ~ 23 对象.getMinutes() 获取 分钟 取值为 0 ~ 56 对象.getSeconds() 获取 秒 取值为 0 ~ 59 对象.getMilliseconds() 获取 毫秒 取值为 0~1000 - ⚠ 注意:
- 周日是一周的开始 -> 周日 = 0
- 当前月份 = 获取的月份 + 1
- ⚠ 得到的都是 数字型
4.3 时间的另一种写法
- 时间对象.toLocaleString() :年月日时分秒
- 时间对象.toLocaleDateString() :年月日
- 时间对象.toLocaleTimeString() :时分秒
- 代码展示:
// 获得当前系统时间 const systemTime = new Date() // 从 获取的当前系统时间(systemTime)里找 // 获取年份 const year = systemTime.getFullYear() // 获得月份 const month = systemTime.getMonth() + 1 // 获取月份中的某一天 const date = systemTime.getDate() // 获取星期 const day = systemTime.getDay() // 获取小时 const hours = systemTime.getHours() // 获取分钟 const minutes = systemTime.getMinutes() // 获取秒 const seconds = systemTime.getSeconds() console.log(systemTime); console.log(`${year} 年 ${month} 月 ${date} 日 周${day} ${hours} 时 ${minutes} 分 ${seconds} 秒`) // Wed Aug 03 2022 21:14:56 GMT+0800 (中国标准时间) // 2022 年 8 月 3 日 周3 21 时 14 分 56 秒
- 格式化时间:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> <style>* {margin: 0;padding: 0;box-sizing: border-box;}div {margin: 100px auto;width: 600px;height: 100px;border: 5px solid #969696;background-color: #d7d7d7;color: hsl(338, 100%, 50%);font-size: 44px;font-weight: 700;font-family: '华文隶书';text-align: center;line-height: 100px;} </style> </head><body><div></div><script>// 写法一: const div = document.querySelector('div')function getTime() {const date = new Date()let hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()let minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()let seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()return `当前时间:${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${hours}:${minutes}:${seconds}`}div.innerHTML = getTime()setInterval(function () {div.innerHTML = getTime()}, 1000)// 当前时间:2022-8-3 22:45:50// 写法二:自动补0/*// 定时器外面再写一次的原因:定时器隔1s再去执行,用外面的填补页面空白div.innerHTML = date.toLocaleString()// div.innerHTML = date.toLocaleDateString()// div.innerHTML = date.toLocaleTimeString()setInterval(function () {const date = new Date()div.innerHTML = date.toLocaleString() // 2022/8/3 23:00:00// div.innerHTML = date.toLocaleDateString() // 2022/8/3// div.innerHTML = date.toLocaleTimeString() // 22:48:20}, 1000)*/</script> </body> </html>
4.3 时间戳
- 使用场景:倒计时
- 时间戳: 是指1970年01月01日00时00分00秒起 至现在 的 毫秒数
- 注意:
- 时间戳 是 唯一的
- ⚠ 中国 在 东8区
const date = +new Date('1970-01-01 00:00:00') / 1000 / 60 / 60 console.log(date) // -8
- ⚠🔻 算法:
- 将来的时间戳 - 当前的时间戳 = 剩余时间毫秒数
- 剩余时间毫秒数 转换为 剩余时间的 日时分秒 就是 倒计时
- 展示:
将来时间戳 2000ms - 现在时间戳 1000ms = 1000ms 1000ms 转换时分秒就是 0小时0分1秒
- 三种获取时间戳的方法:
- 1️⃣ 使用 getTime() 方法
- 语法:
const date = new Date() console.log(date.getTime()) // 1659539589145 毫秒数 // new Date().get.Time() 拓展: 时间对象.getTime() 和 时间对象.valueOf() 的到的结果一样 console.log(date.getTime() === date.valueOf()) // true
- ⚠ 注意:
- 必须 先 实例化
- ⚠ 可以返回 指定时间的时间戳
- 语法:
- 2️⃣ ✔简写 +new Date()
- 语法:
console.log(+new Date()) // 1659539732765 毫秒数
- ⚠ 注意:
- + -> 正号 (隐式转换)
- ⚠ 可以返回 指定时间的时间戳
- 代码展示:
conlose.log(+new Date('2022-10-1 07:30:00')) // 1664580600000 -- 指定时间的时间戳
- 代码展示:
- 语法:
- 3️⃣ 使用 Date.now()
- 语法:
console.log(Date.now()) // 1659540040487 毫秒数
- ⚠ 注意:
- 没有 实例化
- ⚠ 只能得到 当前的 时间戳
- 语法:
- 1️⃣ 使用 getTime() 方法
- 时间转换公式
- 通过 时间戳 得到是 毫秒,需要转换为秒在计算
- 转换公式:
- days: d = parseInt(总秒数 / 60 / 60 / 24)
- hours: h = parseInt(总秒数 / 60 / 60 % 24)
- minutes: m = parseInt(总秒数 / 60 % 60)
- seconds: s = parseInt(总秒数 % 60)
- ✔ 倒计时函数:
const element = document.qurySelector('css选择器') function getCountTime(time) {// 得到当前的时间戳(毫秒)const now = +new Date()// 得到未来时间时间戳(毫秒)const last = +new Date(time)// 得到剩余的时间戳(毫秒) 并转换为 秒const count = (last - now) / 1000// 将 剩余秒数 -> 天、时、分、秒let day = parseInt(count / 60 / 60 / 24)let hours = parseInt(count / 60 /60 % 24)// 补0hours = hours < 10 ? '0' + hours : hourslet minutes = parseInt(count / 60 % 60)// 补0minutes = minutes < 10 ? '0' + minutes : minuteslet seconds = parseInt(count % 60)// 补0seconds = seconds < 10 ? '0' + seconds : secondsreturn `${day} 天 - ${hours}:${minutes}:${seconds}` }function getRemainingTime(element, time) {// 先执行一次:定时器过1s再去执行,会有1s的显示空白时间,让它限制性,填补空白,再让后面的覆盖element.innerHTML = getCountTime(time)setInterval(function () {element.innerHTML = getCountTime(time)}, 1000) }getRemainingTime(div, '2022-10-1 00:00:00')
五、❗❗ 节点操作
- 浏览器 使用 对象 来 记录 网页内容
- 浏览器把网页内容翻译成一个个的对象,把 网页内容 的 特征 翻译成 对象 的 属性
- 这个对象就称为 DOM对象
- 网页内容的特征:
- 标签属性
- 标签内容
- 标签上下级
- …
- 网页内容 、对象
- 网页内容: 标签、文本、注释
- DOM对象:标签(元素)节点、文本节点、注释节点
- 网页内容 和 DOM对象 一 一 对应
- DOM树
- 每个DOM对象中都有表示层级关系的属性,这些属性把所有DOM对象联系在一起,形成一个树状结构,称为DOM树
- DOM树 === 网页
5.1 DOM节点
- DOM节点: DOM树 里面 每一个内容 都称之为 节点
- 节点类型:
- 1️⃣ ❗✔元素节点:
- 所有的 标签
- html 是 根节点
- 2️⃣ 属性节点:
- 所有的属性
- 3️⃣ 文本节点:
- 所有的文本
- 1️⃣ ❗✔元素节点:
-
5.2 查找节点 - 属性
- 有效返回值 是一个 对象
- 无效返回值 - null
5.2.1 父节点
- 1️⃣ parentNode属性
- 语法:
子元素.parentNode
- 返回值:
- ⚠ DOM对象
- 最近一级 的父节点(亲爸爸),找不到 返回 null
- 代码展示:
<div class="yeye"><div class="dad"><div class="baby">x</div></div> </div><script>const baby = document.querySelector('.baby')console.dir(bady) // div.bady -> DOM对象console.dir(baby.parentNode) // div.dad -> DOM对象console.dir(baby.parentNode.parentNode) // div.yeye -> DOM对象 </script>
- 关闭广告:
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.box {position: relative;width: 1000px;height: 200px;background-color: pink;margin: 100px auto;text-align: center;font-size: 50px;line-height: 200px;font-weight: 700;}.box1 {position: absolute;right: 20px;top: 10px;width: 20px;height: 20px;background-color: skyblue;text-align: center;line-height: 20px;font-size: 16px;cursor: pointer;}</style> </head><body><div class="box">我是广告<div class="box1">X</div></div><div class="box">我是广告<div class="box1">X</div></div><div class="box">我是广告<div class="box1">X</div></div><script>// const smallBox = document.querySelectorAll('.box1')/* for (let i = 0; i < smallBox.length; i++) {smallBox[i].addEventListener('click', function () {this.parentNode.style.display = 'none'})} */// 事件委托document.body.addEventListener('click', function (e) {if (e.target.className === 'box1') {e.target.parentNode.style.display = 'none'}})</script> </body></html>
- 语法:
5.2.2 子节点
- 1️⃣ ❌childNodes 属性
- 语法:
父元素.childNodes
- 返回值: 获得 所有子节点、包括文本节点(空格、行换)、注释节点等
- 语法:
- 2️⃣ ⚠🔻 children 属性
- 语法:
父元素.children
- ⚠ 返回值: 伪数组 (要想得到里面的每一个节点还是要遍历
- ⚠ 注意:
- 仅获得 所有 元素节点(标签)
- 只选亲儿子,只不过是把亲儿子里面包含的所有节点(元素、文本、注释…)拿过来
- 代码展示:
<ul><li>1<p>6</p><span>7</span></li><li>2</li><li>3</li><li>4</li><li>5</li> </ul><script>// 获取子节点// 语法:父元素.children// 返回值:伪数组// 仅 获得 所有 元素节点(标签)console.log(document.querySelector('ul').children);// 得到的是一个伪数组 </script>
- 语法:
5.2.3 兄弟节点
- 1️⃣ 下一个 兄弟节点
- nextElementSibling 属性
- 语法:
兄弟元素.nextElementSibling
- ⚠ 返回值:
- 有下一个兄弟节点,得到的就是下一个元素
- 没有 就是 null
- 2️⃣ 上一个 兄弟节点
- previousElementSibling 属性
- 语法:
兄弟元素.previousElementSibling
- ⚠ 返回值:
- 有上一个兄弟节点,得到就是上一个元素
- 没有 就是 null
- 代码展示:
<ul><li>1<p>6</p><span>7</span></li><li>2</li><li>3</li><li>4</li><li>5</li> </ul><script>// 上一个兄弟节点// 语法:兄弟元素.previousElementSibling// 下一个兄弟节点// 语法:兄弟元素.nextElementSiblingconsole.log(document.querySelector('ul li:nth-child(2)').nextElementSibling) </script>
5.3 增加节点
- 先 创建 再 追加
5.3.1 创建节点
- 语法:
document.createElement('标签名') // 文档.创建元素
- 创建的节点是一个正常的DOM对象
- ⚠ 注意:
document.createElement() -- 创建的是空标签
5.3.2 追加节点
- 1️⃣ 插入到 父元素 的 最后一个 子元素
- 语法:
父元素.appendChild(要插入的元素) // 追加孩子
- ⚠ 注意: 做为 父元素 里面 的 最后一个 子元素
- 代码展示:⬇
- 语法:
- 2️⃣ 插入到 父元素 中 某个子元素 的 前面
- 语法:
父元素.insertBefore(要插入的元素, 在哪个元素前面) // 插入在…之前
- ⚠ 注意: 插入到 父元素 里面 的 指定位置
- 代码展示:⬇
- 语法:
- ⚠ 注意: appendChild 和 insertBefore 如果插入的是页面上 已经存在 的标签,会有 剪切 效果(将已经存在的元素 从 原位置 剪切到 新位置)
- 代码展示:
<style>div,li {font-size: 20px;text-align: center;line-height: 50px;}li:first-child {width: 150px;height: 50px;background-color: #b8f0e8;}li:last-child {width: 150px;height: 50px;background-color: #a6a6db;}div {width: 150px;height: 50px;background-color: #c0bfbf;} </style><body><ul><li>我是老大</li></ul><script>// 增加节点(节点 -> 元素节点)// 1.创建节点// 语法:document.createElement('标签名称')// 2.插入节点// (1).作为父元素里面的最后一个子元素// 语法:父元素.appendChild(要插入的元素)// (2).插入到父元素里面指定位置(插入到父元素里面某个子元素的前面)// 语法:父元素.insertBefore(要插入的元素, 在那个子元素前面)// 1.创建节点const li = document.createElement('li')li.innerHTML = '我是老二'// 2.插入节点// 2.1获取父元素const ul = document.querySelector('ul')// 2.2作为父元素里面的最后一个子元素ul.appendChild(li)// 1.创建节点const div = document.createElement('div')div.innerHTML = '我是老大的大哥'// 2.插入节点// 2.1获取父元素const body = document.body// 2.2插入到父元素指定位置(插入到父元素里面指定元素前面)body.insertBefore(div, ul)// 将创建的节点始终插入到父元素的最前面/*body.children // 包含body下所有的(亲)子节点伪数组body.insertBefore(div, body.children[0])*/</script> </body>
5.3.3 克隆节点
- 特殊情况 的 新增节点
- 应用场景:轮播图
- 步骤:
- 1️⃣ 复制 一个 原有 的 节点
- 2️⃣ 把 复制的节点 放入到 指定 的 元素内部
- 语法:
元素.cloneNode(布尔值)
- clondNode会克隆出一个跟原标签一样的标签(原标签上面有什么,克隆后的标签上面就有什么)(是两个元素,克隆成功后前后两个元素没有任何关系)
- 参数:
- true - 深克隆: 克隆时 包含 后代节点 一起克隆 (节点 -> 文本节点、注释节点等所有的节点)
- false - 浅克隆: 克隆时 不包含 后代节点、
- 默认值 为 false
- 代码展示:
<ul><li>1</li><li>2</li><li>3</li> </ul><script>const ul = document.querySelector('ul')// const newLi = ul.children[0].cloneNode(true)// newLi.innerHTML = 'newLi'// ul.appendChild(newLi)ul.insertBefore(ul.children[0].cloneNode(true), ul.children[11]) </script>
5.4 删除节点
- 在 JavaScript 原生DOM操作中,要 删除元素 ⚠ 必须 通过 父元素 删除
- 语法:
父元素.removeChild(要删除的元素)
- ⚠ 注意:
- 如果 不存在 父子关系 则 删除 不成功
- 删除节点 和 隐藏节点(display: none;)有区别
- 删除节点:从DOM中删除节点
- 隐藏节点:只是在页面上不显示,DOM节点依然存在
- ✔ 补充:
- 语法: 自杀式z
删除的元素.remove()
- 语法: 自杀式z
- 拓展:
- 替换节点:
- 语法:
parentNode.replaceChild(newChild, oldChild);
- 方法用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点
- 重绘 和 回流
- 重绘: 由于节点(元素)样式的改变并不会影响它在文档流中的位置和文档布局时,则是重绘
- 回流: 元素的尺寸、结构、布局等发生变化时,浏览器就会重新渲染部分或全部文档的过程称为回流
- 重绘不一定一起回流,但回流一定会引起重绘
- 简单理解,影响到了布局,就会有回流
六、❌ M端事件
- 常见的触屏事件(touch)
-
触屏 touch 事件 说明 touchstart 手指 触摸 到一个DOM元素时触发 touchmove 手指在一个DOM元素上 滑动 时触发 touchend 手指从一个DOM元素上 移开 时触发
七、❗ JS插件
- 熟悉官网,了解这个插件可以完成什么需求 https://www.swiper.com.cn/
- 看在线演示,找到符合自己需求的demo https://www.swiper.com.cn/demo/index.html
- 查看基本使用流程 https://www.swiper.com.cn/usage/index.html
- 查看APi文档,去配置自己的插件 https://www.swiper.com.cn/api/index.html
- 注意: 多个swiper同时使用的时候, 类名需要注意区分
- 使用步骤:
- 引入资源
- css文件
- js文件
- 导入代码
- 复制html结构
- 复制css样式
- 复制js行为
- 引入资源
八、❗❗ window对象
window(JS中的顶级对象) > BOM(浏览器对象模型) > DOM(页面文档对象模型)
8.1 BOM(浏览器对象模型)
- BOM(Browser Object Model)- 浏览器对象模型
- 由一些列相关的对象构成,并且每个对象都提供了很多方法和属性
- 浏览器的内容被翻译成了对象
-
- window 对象是一个 全局对象,也可以说是 JavaScript 中的 顶级对象
- 像document、alert()、console.log()这些都是window的属性,基本BOM的属性和方法都是window的
- ⚠ 所有通过 var 定义在 全局作用域 中的 变量、函数 都会变成 window对象 的 属性 和 方法
- ⚠ window对象下的属性和方法调用的时候可以 省略window
- DOM 和 BOM 区别:
-
8.2 定时器 - 延时函数
- 定时器 = 间歇函数(setInterval()) + 延时函数(setTimeout())
- 让代码 延迟 执行的函数 - setTimeout()
- 语法:
setTimeout(回调函数, 等待的毫秒数)
- 清除延时函数:
let timerId = serTimeout(回调函数, 等待的毫秒数) clearTimeout(timerId)
- ⚠ 注意:
- setTimeout 仅仅 只执行 一次 ,平时省略 window
- 延时函数需要等待,所以后面的代码先执行
- 每一次调用延时器都会 产生一个 新的 延时器
- 间歇函数 和 延时函数 的区别:
- 间歇函数:每隔一段时间就执行一次,除非手动清除
- 延时函数:执行一次
8.3 JS执行机制
- JS代码 从上到下 执行
- 单线程: 同一时间只能做一件事
- 所有的任务需要排队,前一个任务结束,才会执行后一个任务
8.3.1 同步 与 异步
- 1️⃣ 同步
- 前一个任务结束后再执行后一个任务,程序的执行顺序 和 任务的排列顺序 是 一致的
- 同步任务: 都在 主线程 执行栈 上执行
- 2️⃣ 异步
- 如果执行一个任务需要花费一定的时间,在执行这个任务的同时可以去执行别的任务
- 耗时 的都是 异步
- JS的 异步 是通过 回调函数 实现的
- 异步任务的三种类型
- 普通事件(click、mouseenter、mouseleave、……)
- 资源加载
- 定时器 (间歇函数(setInterval) + 延时函数(setTimeout))
- 异步任务 添加到 任务队列 (消息队列)中
- 同步 和 异步 的 本质 区别:
- 一条流水线上的 各个流程 执行顺序不同
- 3️⃣ 执行机制:
- ① 先执行 任务栈 中的 同步任务
- ② 异步任务 添加到 任务队列 里面
- 对 异步任务 进行 排序(根据每个异步任务所消耗的时间 )
- ③ 一旦 执行栈 里面的 所有 同步任务 执行完毕,系统 就会 按次序 读取 任务队列 中的 异步任务,于是 被读取 的 异步任务 结束 等待状态,进入 执行栈,开始执行。
-
8.3.2 事件循环 - event loop
-
- 由于 主线程 不断的 重复 获得任务、执行任务、再获取任务、再执行,所以这种机制被称为 事件循环(enevt loop)
- 事件循环: js执行代码时,会把同步任务添加到主线程执行栈中执行,把满足条件的异步任务推到任务队列排队等候执行,事件循环是一种轮询机制,当执行栈中的所有同步任务执行完毕之后,系统就会依次读取任务队列中的异步任务,异步任务结束等待状态,按照次序添加到执行栈中执行。
8.4 location 对象
- location 的 数据类型 是 对象,它 拆分 并 保存 了 URL地址 的 各个 组成 部分
- 常用 属性 和 方法:
- 1️⃣ ✔🔺 href: 属性 获取 完整的URL地址,对其 赋值时 用于 地址的跳转
-
const btn = document.querySelector('button'); btn.addEventListener('click', function () {location.href = 'https://www.baidu.com'; });
- 可以后退
-
- 2️⃣ search: 属性 获取地址中 携带的参数,符号 ? 后面部分
-
console.log(location.search); // 字符串
-
- 3️⃣ hash: 属性 获取地址中的 哈希值,符号 # 后面部分
-
console.log(location.hash); // 字符串
-
- 4️⃣ reload(是否使用缓存): 方法 用来 刷新 当前 新页面,传入参数 true 时表示 强制刷新,默认false使用缓存刷新
-
const btn = document.querySelector('.reload'); btn.addEventListener('click', function () {// F5 -> 刷新//location.reload();// F5+Ctrl -> 强制刷新 location.reload(true); });
-
- 5️⃣ replace(): 方法 页面跳转(覆盖旧地址)
-
const btn = document.querySelector('button'); btn.addEventListener('click', function () {location.replace('https://www.baidu.com'); });
-
- ⚠ href属性 和 replace()方法 实现页面跳转的区别:
- href属性: 保留 原地址,具有回退功能
- replace()方法: 覆盖 原地址,没有回退功能
- 1️⃣ ✔🔺 href: 属性 获取 完整的URL地址,对其 赋值时 用于 地址的跳转
8.5 navigator 对象
- navigator 的 数据类型 是 对象,该对象记录了 浏览器 自身的 相关信息
- 常用 属性 和 方法:
- 浏览器相关信息:navigator.userAgent
- 通过 userAgent 检测 浏览器 的 版本 及 平台
// 检测userAgent(浏览器信息) !(function () {const userAgent = navigator.userAgent;// 验证是否为Android或iPhoneconst android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/);const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/);// 如果是Android或iPhone,则跳转至移动站点if (android || iphone) {location.href = 'http://m.itcast.cn';} })();
8.6 history 对象
- histroy 的 数据类型 是 对象,主要管理历史记录,该对象与浏览器地址栏的操作相对应。
- 常用属性和方法:
- back(): 可以 后退 功能
- forward(): 前进 功能
- go(参数): 前进 后退 功能
- 参数:
- 1: 前进 一个页面 (back())
- 0: 刷新页面(使用缓存刷新) (reload())
- -1: 后退 一个页面 (forward())
- 参数:
- 代码展示:
<button>后退</button> <button>前进</button> <script>// 获取元素const back = document.querySelector('button');const forward = back.nextElementSibling;// 事件侦听-点击事件back.addEventListener('click', function () {// 前进一步history.go(1);});forward.addEventListener('click', function () {// 后退一步history.go(-1);}); </script>
九、❗❗ 本地存储
- 数据存储 在 用户 浏览器 中(硬盘)
- 设置、读取方便、甚至 页面刷新 不会丢失 数据
- 容量较大、sessionStprange 和 localStorage 约5M
- 为什么要将数据存储到本地存储里?
- 数据持久化(数据不丢失)
9.1 本地存储分类
9.1.1 localStorage
- 作用: 可以 将 数据 永久存储 在 本地(用户电脑),除非手动清除,否则关闭页面 也会 存在
- 生命周期: 什么时候失效,什么时候死掉
- 特性:
- 可以多窗口(页面)共享(同一浏览器可以共享)(不能跨域(同一个域名)使用)
- 以 键值对 的形式 存储使用
- ⚠🔻 语法:
- 1️⃣ 存储/修改 数据:
localStorage.setItem(key, value) // 设置每个小项,key和value要加引号,key和value可以是变量
- 有 这个键就是 修改,没有 就是 添加
- 代码展示:
// 本地存储 - localStorage // 存储数据 - localStorage.setItem(key, value); // 要加引号 localStorage.setItem('uname', '邵秋华');
- 2️⃣ 获取 数据:
localStorage.getItem(key) // 获取里面的项,key必须加引号
- 返回值:
- 有这个key,就返回对应的值
- 没有这个key,返回 null
- 代码展示:
// 获取数据 - localStorage.getItem(key) // 要加引号 console.log(localStorage.getItem('uname')); // 邵秋华
- 返回值:
- 3️⃣ 删除 某项数据:
localStorage.removeItem(key) // 移除里面的项, key必须加引号
- 代码展示:
// 删除本地存储 localStorage.removeItem('uname');
- 代码展示:
- 4️⃣ 清空 数据:
localStorage.clear()
- 慎用
- 清空全部数据
- 1️⃣ 存储/修改 数据:
- ⚠⚠ 注意:
- ⚠ 所有的 键 必须加 引号
- 有这个键就是修改,没有就是添加
- ⚠🔺 本地存储 只能存储 字符串 类型的数据
- 得到的值也是字符串型
- 如果value写的是数值型,存的时候会转换成字符型
- 代码展示:
const arr = [1, 2, 3, 4]; arr.forEach((item, index) => {localStorage.setItem(`id:${index}`, item);console.log(localStorage.getItem(`id:${index}`)); // 1 2 3 4(字符串)console.log(typeof (localStorage.getItem(`id:${index}`)));// string });
9.1.2 sessionStprange
- 特性:
- 生命周期 为 关闭浏览器窗口
- 在同一个窗口(页面)下 数据可以共享
- 以 键值对 的形式 使用
- 用法跟localStorage基本相同
- ⚠ localStorage 与 sessionStorage 的区别
- 他们的 作用 相同,但是 存储方式 不同,因此应用场景也不同
- localStorage 的数据可以 长期存储,关闭浏览器 数据 也 不会消失,除非 手动清除
- sessionStorage 的数据时是 临时存储,页面被关闭,存储在sessionStorage里的 数据 会被 清除
9.2 存储复杂数据类型
- 本地存储 只能存储 字符串,不能存储 复杂数据类型
- JSON:
- 属性和值都有引号,而且是双引号
- 一种字符串格式的名称
- 把 数组/对象 转换为结构为 ”数组/对象“ 的字符串
- 只能存:数字、字符串、对项
- 不能存null、undefined、函数
- ⚠ JSON.parse(转换数据):要转换的数据不是JSON格式的字符串
- 存储复杂数据类型步骤:
- 1️⃣ 将 复杂数据类型 ➡ JSON字符串
- 语法:
JSON.stringify(复杂数据类型)
- 代码展示:
// 本地存储只能存储字符串,不能存储复杂数据类型 // 如果要存储复杂数据类型,需要将复杂数据类型转换成 JSON 字符串 // 语法:JSON.stringify(复杂数据类型); let obj = {uname: '邵秋华',age: 22,gender: '男', };localStorage.setItem('obj', JSON.stringify(obj));
- 语法:
- 2️⃣ 将 JSON字符串 ➡ 复杂数据类型
- 语法:
JSON.parse(JSON字符串)
- 代码展示:
console.log(JSON.parse(localStorage.getItem('obj')));
- 语法:
- 1️⃣ 将 复杂数据类型 ➡ JSON字符串
- 存:
- 复杂数据类型 -> JSON.stringify() -> JSON字符串 -> 存到本地存储中
- 取:
- 从本地存储中取 -> JSON字符串 -> JSON.parse() -> 复杂数据类型
十、❗ 正则表达式
- 正则表达式(Reular Expression):用于 匹配 🔺字符串🔺 中 字符组合 的 模式。
- 在 JavaScript 中,正则表达式 也是 对象(object )
- ⚠🔺 注意: 只能对 字符串 进行匹配
- 正则表达式的作用:
- 1️⃣ 表单验证(匹配)
- 2️⃣ 过滤敏感词汇(替换)
- 3️⃣ 字符串中提取我们想要的部分(提取 ->-爬虫)
10.1 正则表达式的使用
- 1️⃣ 定义规则:
- 语法:
const regObj = /表达式/ // 正则表达式不改变使用
const regObj = new RegExp('表达式') // 正则表达式变化使用
- ⚠ 注意:
- // 正则表达式 的 字面量
- ⚠ // 中间写什么,就查找什么
- ⚠🔺 // 中间 不要乱加 空格
- 只要涉及到正则表达式不要乱加空格,最好用vs格式化
- 语法:
- 2️⃣ ✔检测查找是否匹配:
- 语法:
- test() :用来 查看 正则表达式 与 指定的字符串 是否匹配
-
regObj.test(被检测的字符串)
- ⚠ 返回值:
- 匹配 ➡ true
- 不匹配 ➡ false
- 规则在前面,被检测的就是用户输入的内容
- 注意:
- 语法:
- 代码展示:
// 正则表达式 // 正则表达式使用 // 1)定义规则 // 语法:const 变量名(regObj) = /表达式/; // 注意:正则表达式的字面量中间 不要乱加空格 // 字面量中间些什么就匹配什么(不要乱加空格) // 2)是否匹配 // 语法:regObj(字面量).test(被检测的字符串);const reg = /前端/;const str = '我在学习前端,希望学完高薪就业!!!';console.log(reg.test(str)); // true// 注意const reg = / 前端 /;const str = '我在学习前端,希望学完高薪就业!!!';console.log(reg.test(str)); // false// 注意console.log(/哈/.test('哈')); // trueconsole.log(/哈/.test('哈哈')); // trueconsole.log(/哈/.test('二哈')); // true
- 3️⃣ ⭕检索符合规则的字符串:
- 语法:
- exec():在一个 指定字符串 中执行一个 搜索匹配
-
regObj.exec(被检测字符串)
- 返回值:
- 匹配 ➡ 数组
- 不匹配 ➡ null
- 语法:
- 代码展示:
const reg = /前端/; const str = '我在学习前端,希望学完高薪就业!!!'; console.log(reg.exec(str));
- 正则表达式检测查找 test()方法 和 exec()方法 有什么区别?
- text(): 用于判断是否有符合规则的字符串,返回的是一个布尔值,找到 返回 true ,没找到 返回 false;
- exec(): 用于检索(查找)符合规格的字符串,找到 返回 数组,没找到 为 null
10.2 ❗ 元字符
- 字符
- 普通字符
- 大多数的字符仅能够描述它们本身(字母数字)
- 普通字符 只能够 匹配 字符串中 与 它们 相同的字符
- 元字符
- 是一些 具有 特殊含义 的 字符
- 优点: 极大提高了 灵活性 和 强大的匹配功能
- 普通字符
- ⚠🔻 边界符、量词、字符类 组合使用
- 1️⃣ 边界符
- 表示位置,开头和结尾,必须用什么开头,用什么结尾
- 用来提示字符所处的位置
-
边界符 说明 ^ 表示匹配 行首 的文本(以谁开始) $ 表示匹配 行尾 的文本(以谁结束) - 注意:
- ⚠ ^ $ 在一起,表示 必须是 精确匹配
- 代码展示:
console.log(/哈/.test('哈')); // true // 字符串的内容 和 规则相等 console.log(/哈/.test('哈哈')); // true console.log(/哈/.test('二哈')); // trueconsole.log(/^哈/.test('哈')); // true console.log(/^哈/.test('哈哈')); // true console.log(/^哈/.test('二哈')); // flaseconsole.log(/^哈$/.test('哈')); // true console.log(/^哈$/.test('哈哈')); // false -- 精确匹配(字符串的内容、长度必须和规则相等) console.log(/^哈$/.test('二哈')); // flase
-
- 2️⃣ 量词
- 表示重复次数
- 设定 某个模式 的 出现 次数
-
量词 说明 ***** 重复 零次 或 多次 >= 0 + 重复 一次 或 多次 >=1 ? 重复 零次 或 一次 {n} 重复 n次 {n,} 重复 n次 或 更多次 >= n {n,m} 重复 n 到 m 次 n <= 次数 <= m - ⚠🔺注意:
- 🔺n,m🔻 之间 🔺没有空格🔻
- 离量词 最近的(量词的左边) 重复,别的不重复
- ⚠🔺注意:
- 3️⃣ 字符类
- ① [] - 匹配字符集合
- 被检测的数据 只要能和 规则 匹配到 任意🔺一个🔻字符 就是 true,否则就是false
- 代码展示:
后面的字符串只要包含abc中任意一个字符,都返回true console.log(/[abc]/.test('andy')); // true console.log(/[abc]/.test('baby')); // true console.log(/[abc]/.test('cry')); // true console.log(/[abc]/.test('die')); // false
- 精确匹配: 被检测的数据 🔺只能🔻 和 规则 匹配 🔺一个🔻 字符(n选1),要想多个匹配须和量词配合使用
console.log(/^[abc]$/.test('a')); // true console.log(/^[abc]$/.test('b')); // true console.log(/^[abc]$/.test('c')); // true console.log(/^[abc]$/.test('ab')); // false console.log(/^[abc]{1,}$/.test('abc')); // true
- ② - 连字符
- 使用连字符 - 表示一个 范围
- [a-z] : 表示 a~z 26个英文字母都可以
- [a-zA-Z] : 表示大小写都可以
- [0-9] : 表示 0~9 都可以
-
[\u4e00-\u9fa5] 匹配汉字
- 代码展示:
/^[1-9][0-9]{4,}$/ // 第一个数字:1~9;从第二位开始:0~9;可以重复>=4
- ③ ^ - 取反符号
- [] 里加上 ^ 取反符号
- [^a-z] :匹配除了小写字母以外的字符
- ⚠ 注意: 写到 [] 里面
- ④ . 匹配 除了换行符之外的任何单位
- ⑤ 预定义类:某些常见模式的简写方法
-
预定义 说明 \d 匹配 0-9之间 的 任一数字,相当于[0-9] \D 匹配所有 0-9以外 的 字符,相当于[ ^0-9] \w 匹配任意的 字母、数字和下划线,相当于[A-Za-z0-9_] \W 除所有字母、数字和下划线以外的字符,相当于[ ^A-Za-z0-9_] \s 匹配空格(包括换行符、制表符、空格符等),相等于[\t\r\n\v\f] \S 匹配非空格的字符,相当于[ ^\t\r\n\v\f] -
日期:^\d{4}-\d{1,2}-\d{1,2}$
-
-
- ⑥ () 使用小括号将字符包成一个整体
- ⑦ | 或
- ① [] - 匹配字符集合
- 特殊符号写到 [] 里的最后面
10.3 修饰符
- 修饰符 约束 正则表达式的某细节 行为 ,如是否区分大小写、是否支持多行匹配
- 语法:
/表达式/修饰符
- i: (ignore)正则匹配时 不区分 大小写
- g: (global)匹配 所有 满足正则表达式 的 结果 (全局匹配)
- m: 执行多行匹配
- 代码展示:⬇
- replace - 替换
- 语法:
字符串.replace(/正则表达式/, '替换文本')
- 返回值: 替换好的字符串
- 代码展示:⬇
- 替换多个:
字符串.replace(/正则表达式/g, '替换文本')
- 代码展示:⬇
- ✔ 替换多个 并且 不区分大小写:
字符串.replace(/正则表达式/ig, '替换文本') 字符串.replace(/正则表达式/gi, '替换文本')
- ⚠🔺 g i 不区分 前后
- 代码展示:⬇
- 替换多个 并且 不区分大小写:(用正则表达式里面的 或 )
字符串.replace(/正则表达式|正则表达式/, '替换文本')
- ⚠🔺 或(|) 两侧 不要加 空格
- 如果没有小括号,就是将正则表达式分成多份
- 代码展示:⬇
- 代码展示:
// 修饰符:约束正则表达式的细节行为 // 语法: /正则表达式/修饰符 // i(不区分大小写) + g(匹配所有满足正则表达式的结果) // i console.log(/^java$/.test('JAVA')); // false console.log(/^java$/i.test('JAVA')); // true console.log(/^java$/i.test('JavA')); // true// 替换 - replace // 语法:字符串.replace(/正则表达式/, '替换文本') const str = 'java是一门编程语言,学完JAVA工资很高';// 替换一个 const re1 = str.replace(/java/, '前端'); console.log(re1); // '前端是一门编程语言,学完JAVA工资很高'// 替换多个 - g const re2 = str.replace(/java/ig, '前端'); console.log(re2); // '前端是一门编程语言,学完前端工资很高'// 替换多个 - 或(|) (正则表达式里的或)(|两侧不要加空格) const re3 = str.replace(/java|JAVA/g, '前端'); console.log(re3); // '前端是一门编程语言,学完前端工资很高'
- 语法:
- 拓展:
- change - 事件
- 当鼠标离开表单,并且表单值发生变化触发
- change - 事件
相关文章:
JavaScript - 基础+WebAPI(笔记)
前言: 求关注😭 本篇文章主要记录以下几部分: 基础: 输入输出语法;数据类型;运算符;流程控制 - 分支语句;流程控制 - 循环语句;数组 - 基础;函数 - 基础&…...

API调用的注意事项及好处!
API调用是指一个软件系统通过预定格式、协议和框架,向另一个软件系统发送请求并获得响应的过程。 在进行API调用时需要注意以下事项: 1. 认真阅读API文档:在调用API前,一定要认真仔细地阅读相关的API文档,了解API接口…...

ros2中常用命令,与ros1的区别
文章目录 1. ros1 中的rosrun tf tf_echo 在ros2中使用办法2. rqt 中 tf 树的查看3. roscd 在ros2中使用办法4. ros2获取时间的方法: 1. ros1 中的rosrun tf tf_echo 在ros2中使用办法 # ros2 run tf2_ros tf2_echo [reference_frame] [target_frame] ros2 run tf2…...

利用MySQL语句批量替换指定wordpress文章中的图片路径
很多时间我们将服务器中的图片下载到本地,然后删掉,但是有一个问题就是,所有文章中的图片路径还是以前的,没有根据域名来。导致下午某些时间段图片都是无法显示的,后来想到用MySQL直接批量替换,执行才不到1…...

Linux必会100个命令(六十)curl
在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一款很强大的http命令行工具。它支持文件的上传和下载,是综合传输工具。 curl选项比较多,使用man curl或者curl -h获取帮助信息。 -a/--append …...

物联网硬件安全与整改梳理(1)
物联网安全工作梳理(0)_luozhonghua2000的博客-CSDN博客 上篇讲了物联网总体安全知识框架和工作梳理,这篇单独讲下硬件安全方面的问题和整改知识技能点。硬件安全主要分5个方面来讲:硬件安全现状,硬件安全技术分析,典型案例,安全架构整改,安全整改措施。 智能硬件安全总…...

【大数据学习篇3】HDFS命令操作与MR单词统计
1. HDFS命令使用 [rootmaster bin]# su hd[hdmaster bin]$ #查看/目录[hdmaster bin]$ hdfs dfs -ls / 5 #在/目录创建一个为test名字的文件夹[hdmaster bin]$ hdfs dfs -mkdir /test#查看/目录[hdmaster bin]$ hdfs dfs -ls Found 1 itemsdrwxr-xr-x - hd supergroup …...

java中设计模式总结
设计模式是实际工作中写的各种代码进行高层次抽象的总结,其中最出名的当属 Gang of Four (GoF) 的分类了,他们将设计模式分类为 23 种经典的模式,根据用途又可以分为三大类,分别为创建型模式、结构型模式和行为型模式。 有一些重…...

ChatGPT不到1分钟生成全部代码,你就说慌不慌吧?
生成过程视频: 如何使用ChatGPT快速生成代码 (qq.com) 如何使用ChatGPT快速生成SpringBoot集成Dubbo的完整案例 1、Dubbo最新版本有哪些新特性 Dubbo最新版本是2.7.9,于2021年6月发布。以下是该版本的一些新特性: 1)增加Dubbo-go…...

Python进阶知识(1)—— 什么是爬虫?爬文档,爬图片,万物皆可爬,文末附模板
文章目录 01 | 🍒 什么是 P y t h o n 爬虫? \color{red}{什么是Python爬虫?} 什么是Python爬虫?🍒02 | 🍊 怎么发起网络请求? \color{orange}{怎么发起网络请求?} 怎么发起网络请求…...

如何在andorid native layer中加log function.【转】
在开发Android一些应用或是链接库, 在程序代码中埋一些log是一定有需要的, 因为谁也无法保证自己所写出来的程序一定没有问题, 而log机制正是用来追踪bug途径的一种常用的方法. 在andorid中提供了logcat的机制来作log的目的, 在javalayer有logcat class可以用,哪在nativelayer呢…...

FreeRTOS 空闲任务
文章目录 一、空闲任务详解1. 空闲任务简介2. 空闲任务的创建3. 空闲任务函数 二、空闲任务钩子函数详解1. 钩子函数2. 空闲任务钩子函数 三、空闲任务钩子函数实验 一、空闲任务详解 1. 空闲任务简介 当 FreeRTOS 的调度器启动以后就会自动的创建一个空闲任务,这…...

快速生成HTML结构语法、快速生成CSS样式语法以及emmet
快速生成HTML结构语法 1、生成标签直接输入标签名按Tab键即可 比如 div 然后tab键 2、如果要生成多个相同标签,加上就可以了,比如 div3就可以快捷生成三个div 3、如果有父子级关系的标签,可以用 > 比如 ul>li 就可以了 4、如果有兄弟关…...

企业直播该如何做?硬件设备、网络环境、设备连接和观看权限等整个直播流程教程
这是一份面向直播新手的企业直播说明教程,字数较多,完整看完,可能会需要求10分钟,建议您可以【收藏】,如果本文章对您有帮助,就帮助【点个赞】吧~~~ 阿酷TONY / 2023-5-12 / 原创文章 / 长沙 / 文章…...

第4章 静态网站部署
第4章 静态网站部署 Nginx是一个HTTP的web服务器,可以将服务器上的静态文件(如HTML、图片等)通过HTTP协议返回给浏览器客户端 4.1 案例:将ace-master这个静态网站部署到Nginx服务器上 4.1.1 通过Xftp将ace-master到linux服务器…...

免费版的mp3格式转换器有哪些?这三款软件帮你实现!
在娱乐文化越来越丰富的今天,人们越来越追求音乐、视频等娱乐方式,其中音乐作为一种能够治愈心灵的艺术形式备受欢迎。但要欣赏一首美妙的音乐,就需要我们自己去制作、编辑并转换其格式,以适应各种软件如MP3、MP4等格式。 方法一…...

版本控制器git
目录 一、版本控制系统 二、工作流程和使用命令 (1)工作流程 (2)一次完整流程的相关命令 1.初始化1个空的本地仓库 2.克隆方式1个远程仓库到本地仓库 3.新文件添加到暂存区 4.查看仓库状态,显示有变更的文件 5…...

接口自动化测试 vs. UI自动化测试:为什么前者更快,更省力,更稳定?
从入门到精通!企业级接口自动化测试实战,详细教学!(自学必备视频) 目录 前言: 一、什么是接口自动化测试和 UI 自动化测试 二、为什么接口自动化测试效率比 UI 自动化测试高 1.执行速度 2.维护成本 3.…...

看Chat GPT解答《情报学基础教程》课后思考和习题
情报学基础教程课后思考题 情报学经验规律 (一)按照布拉德福定律,设布拉德福常数为5, 当核心期刊数量为20时,外围一区和外围二区期刊数量各是多少? 答: 核心期刊数和外围期刊比例关系:nc: n1: n2 = 1: a : a2 (a称为布拉德福常数) 外围一区期刊数量为20*5=100,…...

线程同步、生产者消费模型和POSIX信号量
gitee仓库: 1.阻塞队列代码:https://gitee.com/WangZihao64/linux/tree/master/BlockQueue 2.环形队列代码:https://gitee.com/WangZihao64/linux/tree/master/ringqueue 条件变量 概念 概念: 利用线程间共享的全局变量进行同…...

(六)实现好友管理:教你如何在即时通信系统中添加好友
文章目录 一、引言1.1 即时通信系统中用户增加好友功能的重要性和应用场景1.2 TCP连接传输用户增加好友请求的基本原理 二、实现用户增加好友功能2.1 实现用户好友列表的展示和管理2.1.1 使用QListWidgetItem控件展示好友列表客户端关键代码展示服务端关键代码展示 三、效果展示…...

使用循环数组和环形链表实现双端队列
本文主要介绍了两种实现双端队列的数据结构 —— 基于环形链表和循环数组。两种实现方式的基本原理和特点,以及详细的Java代码实现和分析。 引言 双端队列(Deque, Double-ended queue)是一种具有队列和栈的性质的数据结构。它允许在两端插入和删除元素,…...

谁想和我一起做低代码平台!一个可以提升技术,让简历装x的项目
序言 正如文章标题所述,最近一段时间低代码这个概念非常的火,但其实在不了解这个东西的时候觉得它真的很炫酷,从那时就萌生了做一个低代码平台的想法。 但随着时间的变化,现在市面上低代码各个业务方向的平台都有了,可…...

知识推理——CNN模型总结(一)
记录一下我看过的利用CNN实现知识推理的论文。 最后修改时间:2023.05.12 目录 1.ConvE 1.1.解决的问题 1.2.优势 1.3.贡献与创新点 1.4.方法 1.4.1 为什么用二维卷积,而不是一维卷积? 1.4.2.ConvE具体实现 1.4.3.1-N scoring 1.5.…...

OpengES中 GLSL优化要点
本文整理一些日常积累的可以优化的方向 一.延迟vector计算 在进行float与vector计算的时候,可以先确定float再计算,不要多个float一起计算 如: highp float f0,f1;highp vec4 v0,v1;v0 (v1 * f0) * f1;优化为 highp float f0,f1;highp vec…...

项目集角色定义
一、项目集经理的角色 项目集经理是由执行组织授权、领导团队实现项目集目标的人员。项目集经理对项目集的领导、 实施和绩效负责,并负责组建一支能够实现项目集目标和预期项目集效益的项目集团队。项目集经 理的角色与项目经理的角色不同。二者之间的差异是基于项…...

Unreal Engine11:触发器和计时器的使用
写在前面 主要是介绍一下触发器和计时器的使用; 一、在Actor中使用触发器 1. 新建一个C类 创建的C类也是放在Source文件夹中的Public和Private文件夹中;选择Actor作为继承的父类;头文件包括一个触发器和两个静态网格,它们共同…...

Qt之信号槽原理
Qt之信号槽原理 一.概述 所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这…...

【MySqL】 表的创建,查看,删除
目录 一.使用Cmd命令执行操作 1.使用( mysql -uroot -p)命令进入数据库 2.创建表之前先要使用数据库 3.创建表之前要先确定表的名称,列名,以及每一列的数据类型及属性 4.创建表 注意: 5.查看所有已创建的表 6.查看单表 …...

Python 字典修改对应的键值
将 key ‘1’ 的值 ‘1’, ‘3’, ‘5’ 字符,修改为 ‘2’, ‘4’, ‘5’ 。 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 python 完全自学教程》,不仅仅是基础那么简单………...