typeScript(二)

变量和数据类型

一、什么是变量

通俗的讲:变量,是用来 存储数据的容器 ,并且是可以 变化 的。
保温杯里泡枸杞 ,变量里面存数据。
枸杞难挡岁月催,杯里再换点当归:枸杞 -> 当归。

 

二、变量的使用

2.1 基本使用--2步走

变量的使用分为两步: 1 声明变量并指定类型 2 给变量赋值。
第一步:声明变量并指定类型
let age: number;
第二步:给变量赋值
age = 18
解释:
  • 使用等号(=)来给变量 age 赋值。

2.2 简化形式

  • 声明变量的同时就赋值(变量的初始化):
let age: number = 18

变量的使用总结:

  • 变量的两种使用方式:1 先声明后赋值 2 声明的同时并赋值(推荐)
  • 第一种:先声明后赋值
// 1 声明变量并指定类型
 let age: number 
// 2 赋值 
age = 18

第二种:声明的同时并赋值(推荐)
let age: number = 18
注意:声明变量的时候要 指定变量的类型

三、 类型注解

3.1 什么是类型注解

接下来我们来看一下typescript中的类型注解。什么是类型注解呢?其实我们在前面已经用过了,我们来看一句示例代码:

let age: number = 18

代码中的 : number 就是类型注解。

3.2 作用

类型注解 :是一种 为变量添加类型约束 的方式。
程序员 和 TS 有个约定。
// 程序员 和 TS 约定:变量 age 的类型为 number(数值类型) 
let age: number = 18
重要: 约定了什么类型,就只能给变量赋什么类型的值
// × 错误演示 
age = 'Hello TS'
额外说明: VSCode 中代码下方的红色波浪线表示代码报错,出 Bug 了。

四、 变量的命名规范

4.1 变量的命名规则

  • 变量名称只能出现: 数字、字母、下划线(_)、美元符号($),并且不能以 数字 开头
let age: number = 18
以下示例中变量名称是否正确:
let 2b  ×
let $name ✅
let first_name ✅
let @email × 

注意:变量名称 区分大小写
// age 和 Age 是两个不同的变量
 let age: number = 18
 let Age: number = 20

4.2 变量的命名规范

  •  代码就是程序员的脸面,规范的代码,能让人觉得专业、优雅。
  • 推荐:变量名称要有意义,顾名思义。
// 有意义,推荐 
let age: number = 18 
// 无意义,不推荐 
let a: number = 18
  • 推荐:使用驼峰命名法(首字母小写,后面每个单词首字母大写)。
let cityName 
let yourAge

总结:

  • 规则:变量名称只能出现 数字、字母、下划线(_)、美元符号($),并且不能以 数字 开头。

    注意:变量名称区分大小写。

  • 规范:变量名称要有意义,顾名思义。

    推荐:使用驼峰命名法(首字母小写,后面每个单词首字母大写)。

交换变量的值

需求:交换两个变量的值(提示:借助于第三个变量)。

// 变量1: 
let num1: number = 33 
// 变量2: 
let num2: number = 2 
// 目标:
num1 的值为2,num2 的值为33。

五、数据类型概述

平时浏览的网页中都有什么形式的内容啊? 文字、图片、视频、音乐等
问题:计算机可以正确的处理这些内容,它是如何区分这些不同形式的内容呢?
回答: 数据类型
  • l TypeScript 中的数据类型分为两大类: 1 原始类型(基本数据类型) 2 对象类型(复杂数据类型)。
  •  常用的基本数据类型有 5 个: number / string / boolean / undefined / null
// 变量 age 的类型是 number(数字类型) 
let age: number = 18
// 此处的 'Hello TS' 是 string(字符串类型)
 console.log('Hello TS')


 

六、 基本数据类型

6.1 数字类型

  • 数字类型:包含整数值和浮点型(小数)值。
// 数字类型:整数 
let age: number = 18 
// 数字类型:小数 
let score: number = 99.9
  • 当然,从另一个维度来看,也可以包含:正数和负数。
// 正数,+直接省略即可 
let salary: number = +10000 
// 负数 
let salaryWithGirlfriend: number = -2000

6.2 字符串类型

  •  字符串:由零个或多个字符串联而成的,用来表示文本信息。
console.log('Hello TS') 
console.log('') // 空字符串
  • 字符串可以使用单引号(')双引号("),推荐:使用单引号
'Hello TS' // 推荐 
"Hello TS"
  • 字符串类型的类型注解为:string,声明变量时要添加类型注解
let food: string = '糖葫芦'

6.3 布尔类型

布尔类型,用来表示
只有两个值,分别是: true false true 表示 false 表示
  • 布尔类型的类型注解为:boolean
// 真 
let isStudying: boolean = true 
// 假 
let isPlayingGame: boolean = false

6.4 undefined、null

共同特点:只有一个值,值为类型本身。
undefined 类型的值为: undefined
null 类型的值为: null
// 类型注解为:
undefined let u: undefined = undefined 
// 类型注解为:
null let n: null = null
  • undefined :表示 声明但未赋值的变量值 (找不到值)。
let u: undefined 
console.log(u) // 变量u的值为 undefined

  • null :表示 声明了变量并已赋值,值为 null (能找到,值就是 null )。

 

总结

  • TypeScript 中常用的基本数据类型有 5 个。
  • 分别是: number (数字类型) / string (字符串类型) / boolean (布尔类型) / undefined /null
    • 重点是:number / string / boolean
补充概念:这些类型的 ,也叫做 字面量 , 也就是从字面上就能看出来它是什么。

18 // 数字字面量 
'保温杯里泡枸杞' // 字符串字面量
 true / false // 布尔字面量 
undefined 
null

运算符

一、运算符概述--5种

运算符 也称为操作符,用来 实现 赋值( = )、算术运算、比较等 功能的符号
常用的运算符:
  • 算术运算符 。加减乘除呀,这我们已经知道了。
  • 赋值运算符 。赋值运算符我们在前面已经用过了,当然我们一会还会看一下。
  • 递增/递减运算符 。这个在我们学习typescript到现在还没用过,待会也会详细讲解。
  • 比较运算符 。比较就是大于呀,小于呀,我们也要做了解的。
  • 逻辑运算符

二、 算术运算符

2.1 概述

​ 算术运算符包含:加(+)、减(-)、乘(*)、除(/)。

算术运算符:它是进行算术运算时使用的符号,用于两个数值之间的计算。

// 加 
console.log(1 + 2) // 3 

// 减 
console.log(2 - 1) // 1 

// 乘 
console.log(2 * 3) // 6 

// 除 
console.log(4 / 2) // 2

2.2 加号的其他作用

注意:+ 号,不仅可以用于加法计算,还能实现字符串拼接。 我们到代码中体验一下:

// 字符串拼接(拼串) 
console.log('周杰' + '伦') // 结果为:'周杰伦' 
思考以下代码的结果:
console.log(1 + 2) // 结果为:3 
console.log(1 + '2') // 结果为:'12' 
console.log('1' + 2) // 结果为:'12' 

规律:加号两边 只要有一边是字符串 ,就执行字符串拼接。

2.3 加号引发的思考

​ 思考一下:既然加号可以跟字符串一起使用,那其他算术运算符(- * /)可以吗? 我们可以检验一下:

console.log(2 - '1')  // 报错:算术运算符的右侧必须是数字类型。
注意:除加号以外,其他 算术运算符只应该跟数字类型一起使用
其他方式:将字符串类型 转换 为数字类型。
console.log(2 - +'1') 
// +'1' 表示将 '1'(string) => 1(number) 
// 所以,2 - +'1' ==> 2 - 1 ==> 结果为:1
  • 记住:在字符串前面添加 + 号,可以string 转化为 number(字符串内容为数字时才有意义)。

三、赋值运算符

赋值运算符:将等号右边的值赋值给它左边的变量,比如:等号(=)。

// 等号:将 18 赋值给左侧的变量
 age let age: number = 18
需求:明年老师 19 岁,让变量 age 变成 19
age = age + 1 

顺序: 1 先执行等号右边的代码 2 将计算结果赋值给等号左边的变量。
除了等号( = )之外,还包括:加等( += )、减等( -= )、乘等( *= )、除等( /= )。
age += 1
说明:其他几个(减等、乘等、除等)同理。

四、 自增和自减运算符

自增( ++ )运算符是 += 1 的简化形式;自减( -- )运算符是 -= 1 的简化形式。
比如:让 age 的值变为 19 ,该如何处理?
let age: number = 18
age += 1 // 加等

更简洁的方式: ++
age++

解释: age ++ 会让变量 age 的值加 1
作用: 自增 ++ )运算符用来实现变量的 值加 1 自减 -- )运算符实现变量的 值减 1
注意: ++ -- ,只能让变量的值增加或减少 1

五、比较运算符

比如:考完试,拿到成绩后,比较分数。

你的100分 大于 同桌的99分

比较运算符:用于 比较两个数据的值 ,并返回其比较的结果,结果为 布尔类型

比较运算符包含 6 个:

  • 大于(>
  • 大于等于(>=
  • 小于(<
  • 小于等于(<=
  • 等于(===
  • 不等于(!==

下面我们通过代码来理解比较运算符:

// 大于
 console.log(1 > 2)   // 结果为:false
// 大于等于
 console.log(3 >= 2)   // 结果为:true 
// 小于 
console.log(1 < 2)    // 结果为:true
// 小于等于
 console.log(3 <= 2)    // 结果为:false
// 相等 
console.log(3 === 4)   // 结果为:false 
// 不相等 
console.log(3 !== 4)    // 结果为:true

问题 1 :比较运算符有什么用? 比较两个数据的值
问题 2 :比较结果是什么类型? 布尔类型
注意:比较运算符常用于 数字类型 的比较。

六、逻辑运算符

生活中,我们常用: 并且 或者 不是 这样的词语,来描述一些事情。
与逻辑运算符一一对应: (并且) 、或 (或者) 、非 (不是)。
情况一:有钱 并且 漂亮( 两个条件同时满足 )。
情况二:有钱 或者 漂亮( 只要某一个条件满足 )。
情况三: 不是 男的( 取反 )。
逻辑运算符通常用于 布尔类型 的计算,并且 结果也是布尔类型
  • 与(逻辑与),用 && 符号来表示。当 && 两边的值同时为true,结果才为true;否则,为false。
true && false // 结果为:false

示例:

// 与 
console.log(2 > 1 && 2 >= 2)  
// 结果为:true
  • 或(逻辑或),用 || 符号来表示。当 || 两边的值只要有一个为true,结果就为true;否则,为false。
true || false // 结果为:true

示例:

// 或 
console.log(3 < 2 || 1 <= 2) 
// 结果为:true
  • 非(逻辑非),符号为 !(叹号),表示取反,即:truefalse falsetrue
!true // 结果为:false

示例:

// 非 
console.log(!false || false) 示例: // 结果为:true

总结:
  •  两个条件同时满足时,再执行操作,用什么? 逻辑与 &&
  • 只要有一个条件满足时,就执行操作,用什么? 逻辑或 ||
  •  逻辑非,表示什么作用? 取反 !

TypeScript 语句

一、 条件语句

1.1 概述

生活中,打开网站看电影: 1 免费电影 2 Vip 电影。
播放 Vip 电影时,首先会判断是不是 Vip
  • 如果是 Vip,就可以看完整电影;
  •  如果不是 Vip,只能试看5分钟。

 

1.2 if 语句

条件语句: 根据判断条件的结果 (真或假),来执行不同的代码,从而 实现不同功能
条件执行时,首先判断条件是否满足。
  • 如果 条件满足,就做某件事情(情况1
  •  如果 条件不满足,就做另外一件事情(情况2

 

条件语句,也叫分支语句,不同的情况就是不同的分支。
TypeScript if 语句就是 实现条件判断 的。
  • if 语句的语法:
if (判断条件) { 
条件满足时,要做的事情 
}
解释:
  • 判断条件:布尔类型(true 或 false)。
  • 如果 判断条件 为真,就执行 要做的事情;
  • 否则,如果判断条件为假,则不执行花括号中的代码。
补充概念说明: 语句 ,是一个完整的句子,用来使某件事情发生(或实现某个功能)。

1.3 else 语句

TypeScript else 语句必须配合 if 语句来使用。
else 语句表示: 条件不满足 ,要做的事情( if 语句的对立面)。
  • else 语句的语法:
if (判断条件) {

条件满足时,要做的事情

} else {

条件不满足,要做的事情

}
解释:
  • 否则,如果 判断条件 为假,就执行 条件不满足时要做的事情

二、 三元运算符

三元运算符的作用与 if...else 语句类似。
作用: 根据判断条件的真假 ,得到不同的 结果
语法:
结果 = 判断条件 ? 值1 : 值2
解释:
  •  如果判断条件为结果为 值1
  • 否则,如果判断条件为结果为 值2
注意:得到 结果的类型 1 2 类型决定 (值 1 和值 2 的类型相同)。

三、 循环语句

3.1 概述

生活中,经常 重复做某件事情 ,比如:
1. 上学时作业写 3 遍。
2. 女朋友说:爱我就对我说 100 遍“我爱你”。
需求:在 TS 中,打印 3 遍以下内容:
'北冥有鱼,其名为鲲。鲲之大,一锅装不下'
TypeScript 中,要实现 重复做某件事情 ,就需要用到 循环语句 ,来减少重复劳动提升效率。

3.2 for 循环

TypeScript 中, for 循环就是实现 重复做某件事情 的循环语句。
注意: for 循环是 TS 基础知识的 重难点 ,语法比较复杂。
上学时作业写 3 遍。先准备,写作业的遍数,默认为: 1
  • 1 遍:先判断遍数是否 <= 3(是);写作业;遍数 + 1(准备开始第2遍)。
  • 2 遍:先判断遍数是否 <= 3(是);写作业;遍数 + 1(准备开始第3遍)。
  •  3 遍:先判断遍数是否 <= 3(是);写作业;遍数 + 1(准备开始第4遍)。
  • 4 遍:先判断遍数是否 <= 3(否);结束写作业。

 

for 循环的组成:
1. 初始化语句:声明 计数器变量 用来记录循环次数( 执行一次 )。
2. 判断条件:判断 循环次数 是否达到目标次数。
3. 计数器更新:完成一次循环让 计数器数量加1
4. 循环体:循环的代码,也就是 要重复做的事情

3.3 for 循环的基本使用

  • 语法:
for (初始化语句; 判断条件; 计数器更新) { 
   循环体 
}
解释:
  • 初始化语句:声明计数器变量,记录循环次数。
  • 判断条件:判断循环次数是否达到目标次数。
  • 计数器更新: 计数器数量加1
  • 循环体:重复执行的代码,也就是 要重复做的事情
// 作业写 3 遍:
for (let i: number = 1; i <= 3; i++) { 
console.log('北冥有鱼,其名为鲲。鲲之大,一锅装不下') 
}

3.4 for 循环的执行过程

意义: for 循环的语法比较复杂,搞明白代码执行顺序,才是真正理解并掌握了 for 循环。
1. 初始化语句: 只会执行一次
2. 重复执行的部分: 判断条件 循环的代码 计数器更新 (绿色框框)。

 

  • 说明:红色表示当前执行的代码。
for (let i: number = 1; i <= 3; i++) { 
console.log('...一锅装不下') 
}
执行过程记录:
// 初始化计数器(i = 1) -- 只执行一次
 // 第 1 次: a 判断条件(1 <= 3)b 循环的代码->打印 c 计数器++(i变为2); 
// 第 2 次: a 判断条件(2 <= 3)b 循环的代码->打印 c 计数器++(i变为3); 
// 第 3 次: a 判断条件(3 <= 3)b 循环的代码->打印 c 计数器++(i变为4); 
// 第 4 次: a 判断条件(4 <= 3),条件不满足,结束循环。

3.5 断点调试

疑问:老师是如何知道 for 循环执行过程的呢? 断点调试
借助断点调试,观察代码的执行过程
断点( Breakpoint ):程序暂停的位置(调试时,程序运行到此处,就会暂停)。

 

3.6 break和continue

break continue 常用在循环语句中,用来改变循环的执行过程。
for 循环执行的特点是: 连续且不间断
例子:买了 5 个包子,吃包子。
for (let i: number = 1; i <= 5; i++) { 
	
	console.log('正在吃第' + i + '个包子') 
}
break 能够让循环提前结束( 终止循环 )。
例子:买了 5 个包子,吃包子。
场景:吃到(没吃)第 3 个饱了,剩下的就不吃了。
for (let i: number = 1; i <= 5; i++) { 
	if (i === 3) { 
		break 
	}
	console.log('正在吃第' + i + '个包子') 
}
continue 能够让循环间断执行( 跳过本次循环,继续下一次循环 )。
例子:买了 5 个包子,吃包子。
场景:吃到第 3 个有虫子,这个就不再吃了,但没吃饱,继续吃下一个。
for (let i: number = 1; i <= 5; i++) { 
	if (i === 3) { 
		continue 
	}
	console.log('正在吃第' + i + '个包子') 
}

四、 断点调试

TypeScript 数组

一、 数组概述

问题 1 :存储一个人的名字,怎么存? 声明一个字符串类型的变量
let name1: string = '迪丽热巴'
问题 2 :存储三个人的名字,怎么存? 声明三个字符串类型的变量
let name1: string = '迪丽热巴'
let name2: string = '古力娜扎'
let name3: string = '马尔扎哈'
问题 3 :如何是存储一个班级中所有人的名字呢?
存储多个数据 时,声明多个变量就太繁琐了。
数组,是用于 存放多个数据的集合
有数组:只需要使用一个数组( [] ),就可以存储任意多个数据。
let names: string[] = ['迪丽热巴', '古力娜扎', '马尔扎哈']
没有数组:存储三个人的名字,就需要三个字符串类型的变量。
let name1: string = '迪丽热巴'
let name2: string = '古力娜扎'
let name3: string = '马尔扎哈'
注意:数组中,通常是 相同类型 的数据。

二、 创建数组---2种方式

创建数组有两种语法形式。
  •  语法一(推荐):
let names: string[] = []
[] (中括号)表示数组。如果数组中没有内容,就是一个 空数组
数组的类型注解由两部分组成: 类型+ [] 。此处表示字符串类型的数组( 只能 出现字符串类型)。
let names: string[] = ['迪丽热巴', '古力娜扎', '马尔扎哈']
数组,多个元素之间使用 逗号( , 分隔。
数组中的每一项内容称为: 元素
  • 语法二(不推荐):
let names: string[] = new Array()

功能与 [] 相同,但是更加繁琐:
let names: string[] = []

数组中有数据时:
let names: string[] = new Array('迪丽热巴', '古力娜扎', '马尔扎哈')
// 相当于:
let names: string[] = ['迪丽热巴', '古力娜扎', '马尔扎哈']

三、 数组长度和索引

3.1 概述

生活中,我们经常会排队(比如:排队吃饭)。
队伍的特征: 1 长度 2 顺序和序号(队伍中的每个人)。
我们可以把 数组想象成这个队伍 ,因为 数组也有长度 ,也有 顺序 并且数组中的每个元素也有 序号

 

3.2 数组长度

数组长度 :表示数组中元素的个数,通过数组的 length 属性来获取。
let foods: string[] = ['煎饼', '馒头', '米饭']
获取数组长度:
console.log(foods.length) // 3

3.2 数组索引

数组中的每个元素都有自己的序号。

我们把数组中元素的序号,称为: 索引(下标) ,数组中的元素与索引一一对应。
注意: 数组索引是从 0 开始的
let foods: string[] = ['煎饼', '馒头', '米饭'] 
// 数组的索引分别为: 0 1 2

问题:该数组的长度( length )和最大索引之间有什么关系? 最大索引为: length - 1
数组是 有序 的集合,用来存储多个数据。

总结:

问题 1:如何获取数组长度?  foods .length
问题 2:数组索引是从几开始的?  索引从 0 开始

四、 取值和存值

4.1 取值

从数组中, 获取 到某一个元素的值,就是从数组中 取值 。(比如,获取最爱的食物 煎饼)
let foods: string[] = ['煎饼', '馒头', '米饭'] 
// 数组的索引分别为: 0 1 2
数组中的元素与索引是一一对应的, 通过索引获取到某一个元素的值
语法:
数组名称[索引]

比如,获取到最爱的食物 煎饼: 

console.log(foods[0]) // 煎饼

4.2 存值

如果要 修改 数组中某个元素的值,就要使用数组 存值 。(比如,不爱吃馒头,将馒头替换为包子)
let foods: string[] = ['煎饼', '馒头', '米饭']
 // 数组的索引分别为: 0 1 2
技巧: 先获取 到要修改的元素,然后, 再存值
语法:
数组名称[索引] = 新值
比如,将馒头替换为包子:
foods[1] = '包子' 
console.log(foods) // ['煎饼', '包子', '米饭']

4.3 添加元素

存值的语法是:数组名称[索引] = 新值,根据索引是否存在,有两种功能:1 修改元素 2 添加元素。

let foods: string[] = ['煎饼', '馒头', '米饭']
 // 数组的索引分别为: 0 1 2
1. 如果 索引存在 ,就表示: 修改 元素。
foods[1] = '包子'
2. 如果 索引不存在 ,就表示: 添加 元素。
foods[3] = '油泼面'
console.log(foods) // ['煎饼', '馒头', '米饭', '油泼面']

添加元素的通用写法: 数组名称[数组长度] = 新值

五、遍历数组

遍历数组,也就是把数组中的所有元素挨个获取一次(比如,计算数组中所有数字的和)。

let nums: number[] = [100, 200, 300]
 // 数组的索引分别为: 0 1 2
通过 数组取值 的方式,就可以一个个取出来:
console.log(nums[0]) // 100 
console.log(nums[1]) // 200 
console.log(nums[2]) // 300
存在问题:太繁琐,相似的代码 重复 多次。
重复做某件事情 ,可以使用 for 循环。
重复取值的规律:索引号自增(每次加 1 ),而 for 循环的 计数器 i 也是自增的。

遍历数组,也就是把数组中的所有元素挨个获取一次(比如,计算数组中所有数字的和)。

let nums: number[] = [100, 200, 300]
 // 数组的索引分别为: 0 1 2
推荐,使用 for 循环遍历数组:
for (let i: number = 0; i <= nums.length - 1; i++) { 
console.log(nums[i])
 }
简化判断条件 (计数器 i 的值为整数,所以, i<=2 i<3 作用相同):
for (let i: number = 0; i < nums.length; i++) { 
console.log(nums[i])
 }

注意 1 :因为 数组索引是从 0 开始的 ,所以计数器 i 的默认值为 0
注意 2 :应该根据数组长度来计算,公式为 数组长度减一 ,也就是: nums.length – 1 (最大索引)。
优势:不管数组中元素的数量怎么变化, for 循环的判断条件不需要改动。

总结:

遍历数组 ,也就是把数组中的所有元素挨个获取一次。
问题 1:如果要遍历数组应该使用什么语句?   for 循环语句
问题 2 for循环计数器的默认值是多少?  默认值为: 0
问题 3 for循环的判断条件是什么?  i < nums.length

TypeScript 函数基础

一、 函数概述

需求:计算数组 nums 中所有元素的和。
let nums: number[] = [1, 3, 5]

let sum: number = 0
for (let i: number = 0; i < nums.length; i++) {
sum += nums[i]
}
console.log(sum)

问题:如果还要计算其他数组(nums2)中所有元素的和呢? 拷贝一份代码,修改
let nums2: number[] = [2, 4, 6]

存在的问题:相似的代码重复写,代码冗余。

正确的姿势:使用 函数 包装 封装 )相似的代码, 在需要的时候调用函数 ,相似的代码不再重复写。
function getSum(nums: number[]) {
let sum: number = 0
for (let i: number = 0; i < nums.length; i++) {
sum += nums[i]
}
console.log(sum)
}
getSum(nums1) // 计算nums1中所有元素的和
getSum(nums2) // 计算nums2中所有元素的和
所谓函数,就是 声明一次 但却可以 调用任意多次的一段代码
意义:实现代码 复用 ,提升开发效率。
封装:将一段代码包装起来,隐藏细节。

二、函数的使用

函数的使用分为两步: 1 声明 函数 2 调用 函数 (类比变量)。
  • 第一步:声明函数
function 函数名称() {
函数体
}

解释:
  •  函数名称:推荐以动词开头,因为函数表示做一件事情,实现一个功能。
  • 函数体:表示要实现功能的代码,复用的代码。
function sing() { 
console.log('五环之歌')
 }
  •  第二步:调用函数
函数名称()

比如,调用 sing 函数:

sing()
注意: 只有调用函数后,函数中的代码才会执行

总结:
1. 函数的基本使用分为哪两步? 1 声明 函数 2 调用 函数
2. 声明函数的关键字是什么?  function
3. 不调用函数,函数中的代码会执行吗? 不会
// 1 声明函数
function sing() {
console.log('五环之歌')
}
// 2 调用函数
sing()

三、函数参数

3.1 概述

需求:让唱歌的函数( sing ),每次调用时, 不同的歌。
function sing() {
console.log('五环之歌')
}
sing() // 五环之歌
sing() // 五环之歌
原因:函数( sing )中歌曲名称是固定值。
存在的问题:函数( sing )只能“唱”固定的歌,太死板,没有体现出函数 复用 的灵活性。

使用函数参数来实现:

// 调用函数时,告诉函数要唱的歌曲名称
sing('五环之歌')
sing('探清水河')
// 声明函数时,接收传入的歌曲名称
function sing(songName: string) {
console.log(songName)
}

函数( sing )中歌曲名称:固定值 -->   动态传入的值。
函数参数 的作用:增加了函数的 灵活性 通用性 ,针对相同的功能,能够适应更多的数据(值)。

3.2 形参和实参

函数参数分为两部分: 1 形参 2 实参。
1. 形参 :声明函数时指定的参数,放在声明函数的 小括号中 (挖坑)。
function sing(songName: string) { }
  •  语法:形参名称: 类型注解,类似于变量声明,但是没有赋值。
  •  作用:指定函数可接收的数据。
然后,就可以在函数体中,像使用变量一样使用形参了。
2. 实参 :调用函数时传入的参数,放在调用函数的 小括号中 (填坑)。
sing('五环之歌')
  •  实参是一个具体的值(比如:字符串18[]等),用来赋值给形参。
形参和实参的总结:
  • 声明函数时的参数,叫什么?作用? 形参,指定函数能够接收什么数据。
  •  调用函数时的参数,叫什么?作用? 实参,是一个具体的值,用来赋值给形参。
function sing(songName: string) { }
sing('五环之歌')
通过形参和实参的配合,函数可以接收动态数据,从而让函数变得更加灵活、强大。

3.3 其他说明

1. 根据具体的功能,函数参数可以有多个,参数之间使用 逗号(,) 来分隔。
function fn(name: string, age: number) { } 
fn('刘老师', 18)
2. 实参和形参按照顺序,一一对应。
function fn(name: string, age: number) { }
 fn('刘老师', 18) // name -> '刘老师', age -> 18

3. 实参必须符合形参的类型要求,否则会报错! 

function sing(songName: string) {} 
sing(18) // 报错! 形参要求是 string 类型,但是,实参是 number 类型。
技巧: 调用函数时,鼠标放在函数名称上,会显示该函数的参数以及类型。
总结:
  • 函数形参是 string 类型,调用该函数时传入 18 对吗?  不对,因为实参不符合形参的类型要求
  •  函数有多个参数时,多个参数之间用什么符号分隔? 逗号
  •  以下代码会报错吗? 报错!因为函数sing要求有一个参数,但是没有传
function sing(songName: string) { }
sing() // 报错!

四、 函数返回值

4.1 概述

函数返回值 的作用: 将函数内部计算的结果返回 ,以便于使用该结果继续参与其他的计算。
需求:计算以下两次调用结果的和。
getSum([1, 3, 5]) // 9 
getSum([10, 100, 1000]) // 1110
getSum([1, 3, 5]) + getSum([10, 100, 1000]) // 9 + 1110 => 1119
关键点: 拿到函数( getSum )内部计算出来的结果 ,然后,才能进行后续的加法计算。
注意:如果没有指定函数的返回值,那么, 函数返回值的默认类型为 void (空,什么都没有)。

4.2 基本使用

步骤: 1 指定返回值类型 2 指定返回值
1. 指定返回值类型
function fn(): 类型注解 {
}

  • 在声明函数的小括号后面,通过 : 类型注解 指定。
function fn(): number {
}
2. 指定返回值
function fn(): 类型注解 {
return 返回值
}
  • 在函数体中,使用 return 关键字来返回函数执行的结果。
function fn(): number {
return 18
}

  • 注意:返回值必须符合返回值类型的类型要求,否则会报错!

1. 使用变量接收函数返回值
let result: 类型注解 = fn()
使用变量接收函数返回值的时候,相当于:直接将返回值赋值给变量。
let result: number = 18
注意:变量( result )的类型与函数( fn )的返回值类型要一致。
然后,就可以使用这个变量(返回值),继续进行其他计算了。
2. 直接使用函数调用的结果(返回值),进行其他计算
console.log( fn() * 10 )
总结:
  • 使用哪个关键字来指定返回值? return
  •  以下代码是否正确?  错误!因为返回值18不符合返回值类型string的要求
function foo(): string {
return 18
}
  •  如果函数(getSum)返回了数组中所有元素的和,以下代码表示什么?
getSum([1, 3, 5]) + getSum([10, 100, 1000])

4.3 return 的说明

1. 将函数内部的计算结果返回。
2. 终止函数代码执行,即: return 后面的代码不会执行。
function fn(): number {
return 18
console.log('我不会执行,放在这,没有意义')
}
3. return 只能在函数中使用,否则会报错。
4. return 可以单独使用(后面可以不跟内容),用来 刻意终止函数的执行
function play(age: number): void {
if (age < 18) {
return
}
console.log('网吧上网好爽啊,王者、吃鸡两不误')
}
play(16) // 情况1:进入if后return,后续代码不执行
play(20) // 情况2:不进if,直接打印内容: 网吧上网好爽啊,王者、吃鸡两不误

注意:如果函数没有返回值,默认返回值类型是: void (空),可省略不写。
function play(age: number) { /* ... */ }

return 的总结:

  • 能否在函数外面使用 return? 不能
  • return 后面不跟内容,单独使用,表示什么?  不会执行
  •  return 后面的代码会执行吗? 刻意终止函数代码执行
  • 函数没有返回值,默认返回值类型是什么? void

函数基础总结

函数,即: 声明一次 但却可以 调用任意多次的一段代码
通过将要实现的功能,使用函数封装起来,实现代码 复用 ,提升开发效率。
函数的三种主要内容: 1 参数 2 函数体 3 返回值。
简化过程:
         1. 输入(参数) -- 可选
        2. 处理(函数体)
         3. 输出(返回值) -- 可选

 

TypeScript 函数进阶

一、函数调试

1.1 基本操作

借助断点调试,观察代码的执行过程
关键点: 1 在哪个位置打断点? 2 如何调试?
一.断点位置:函数调用所在位置。
二.调试函数常用按钮:
单步调试:表示执行下一行代码,但是, 遇到函数调用时,进入函数内部
单步跳出:表示 跳出当前函数 (函数中的代码执行完成),继续执行函数调用后的下一行代码。

 

1.2 函数的执行过程

示例:
function work() {
console.log('早上9点开始工作')
play()
console.log('晚上6点结束工作')
}
function play() {
console.log('早上9:30开始吃鸡')
console.log('晚上5:30结束吃鸡')
}
work()
结论 1 :函数里面,还可以继续调用其他函数。
结论 2 :函数,按照顺序一行行的执行代码,当遇到调用其他函数时,先完成该函数调用,再继续执行代码。

二、 变量作用域

一个变量的作用域指的是:代码中定义变量的区域,它决定了变量的使用范围。
TS (或 JS )中,函数可以形成作用域,叫做:函数作用域。
根据范围的不同,变量可以分为两种: 1 局部变量 2 全局变量。
  • 局部变量:表示在函数内部声明的变量,该变量只能在函数内部使用(局部地区有雨)。
  • 全局变量:表示在函数外部声明的变量,该变量在当前 ts 文件的任何地方都可以使用。
function fn() {
// 变量 num 是局部变量
let num: number = 1
console.log(num) // 此处能访问到变量 num
}
fn()
console.log(num) // 问题:此处能访问到变量 num 吗? 不能
// 变量 num 是全局变量
let num: number = 1
function fn() {
console.log(num) // 问题:此处能访问到变量 num 吗?  能
}
fn()
console.log(num) // 问题:此处能访问到变量 num 吗? 能

TypeScript 对象

一、对象概述

生活中,对象是一个具体的事物,比如:你的电脑、你的手机、古力娜扎、周杰伦(周董)等都是对象。
程序员都知道:万物皆对象。
这些具体的事物,都有自己的特征和行为:
特征:
你的电脑:尺寸、重量、价格等
你的手机:品牌、屏幕大小、颜色等
古力娜扎:年龄、身高、三围等
行为:
你的电脑:浏览网页、写代码等
你的手机:播放视频、吃鸡等
古力娜扎:演电影、配音等
TypeScript 中的对象,是对生活中具体事物的抽象,使得我们可以通过代码来描述具体的事物。
TS 中的对象,也是由特征和行为组成的,它们有各自专业的名称: 属性 (特征)和 方法 (行为)。
  • 理解 TS 中的对象:一组相关属性和方法的集合,并且是无序
// 演示对象:
{
name: '周杰伦',
gender: '男',
height: 175,
sing: funtion () {
console.log('故事的小黄花 从出生那年就飘着')
}
}
疑问:为什么要有对象?
需求:使用 TS 代码描述周杰伦。
方案一:使用多个变量
let name: string = '周杰伦'
let gender: string = '男'
let height: number = 175
function sing() { ... }

缺点:一个变量只能存储一个数据,多个变量之间没有任何关联(相关性)。
疑问:为什么要有对象?
需求:使用 TS 代码描述周杰伦。
方案二:使用数组,一次可以存储多个数据:
['周杰伦', '男', 175, function sing() { ... }]
缺点:不知道数组中的每个元素表示什么。
正确姿势:使用对象,对象在描述事物(一组相关数据)时,结构更加清晰、明了。
{ name: '周杰伦', gender: '男', height: 175, sing: function () { ... }}
总结:
对象: 一组相关属性和方法的 集合 ,并且是 无序
TS 中,如果要描述一个事物或一组相关数据,就可以使用对象来实现。

二、 创建对象

注意:先学习对象的基本使用,再学习对象的类型注解(对象的类型注解类似于对象自身的语法)。
对象的语法:
let person = {}
此处的 {} (花括号、大括号)表示对象。而对象中没有属性或方法时,称为:空对象。
对象中的属性或方法,采用 键值对 的形式,键、值之间使用冒号( : )来配对。

 

键( key)-->名称 ,值(value)-->   具体的数据。
多个键值对之间,通过逗号( , )来分隔(类比数组)。
现在,对象 person 具有两个属性:
let person = { name: '刘老师', age: 18 }
属性和方法的区别: 值是不是函数 ,如果是,就称为方法;否则,就是普通属性。
let person = {
sayHi: function () {
console.log('大家好,我是一个方法')
  }
}
注意:函数用作方法时可以省略 function 后面的函数名称,也叫做匿名函数。
函数没有名称,如何调用? 此处的 sayHi 相当于函数名称,将来通过对象的 sayHi 就可以调用了。
如果一个函数是单独出现的,没有与对象关联,我们称为函数;否则,称为方法。
总结:
对象中的属性或方法,采用 键值对 的形式,因此, 对象是无序键值对的集合
  • 使用什么符号创建对象?     花括号({}
  • 键(key)、值(value)之间通过什么符号配对? 冒号(:
  •  多个属性或方法之间使用什么符号分隔?  逗号(,
  •  属性和方法的区别? 值是不是函数

三、接口

3.1 对象的类型注解

TS 中的 对象是结构化 的,结构简单来说 就是对象有什么属性或方法
在使用对象前,就可以根据需求,提前设计好对象的结构。
比如,创建一个对象,包含姓名、年龄两个属性。
思考过程: 1 对象的结构包含姓名、年龄两个属性 2 姓名 --> 字符串类型,年龄-->   数值类型 3 创建对象。

 

这就是对象的结构化类型(左侧),即:对该对象值(右侧)的结构进行类型约束。
或者说: 建立一种契约,约束对象的结构
语法说明:

 

对象类型注解的语法类似于对象自身的语法。
注意:键值对中的 值是类型! (因为这是对象的类型注解)。
注意:多个键值对之间使用分号( ; )分隔,并且分号可省略。
总结:
TS 中的 对象是结构化 的,在使用对象前,就可以根据需求,提前设计好对象的结构。
对象的结构化类型(类型注解): 建立一种契约,约束对象的结构

 

注意点:类型注解中键值对的值为 类型

3.2 对象方法的类型注解

问题:如何给对象中的方法,添加类型注解?
技巧:鼠标放在变量名称上, VSCode 就会给出该变量的类型注解。
let person: {
sayHi: () => void
sing: (name: string) => void
sum: (num1: number, num2: number) => number
}
箭头( => )左边小括号中的内容:表示方法的参数类型。
箭头( => )右边的内容:表示方法的返回值类型。
方法类型注解的关键点: 1 参数 2 返回值。
注意:技巧是辅助,更重要的是理解。

3.3 接口的使用

直接在对象名称后面写类型注解的坏处: 1 代码结构不简洁 2 无法复用类型注解。
接口:为对象的类型注解命名,并为你的代码建立契约来约束对象的结构。
语法:

 

interface 表示接口,接口名称约定以 I 开头。
推荐:使用接口来作为对象的类型注解。

四、 取值和存值

4.1 取值

取值,即:拿到对象中的属性或方法并使用。
获取对象中的属性,称为:访问属性。
获取对象中的方法 并调用 ,称为:调用方法。
  • 访问属性
let jay = { name: '周杰伦', height: 175 }
需求:获取到对象( jay )的 name 属性。
console.log(jay.name)
说明:通过 点语法( . 就可以访问对象中的属性。
技巧:在输入点语法时,利用 VSCode 给出来的提示,利用上下键快速选择要访问的属性名称。

  • 调用方法
let jay = {
sing: function () {
console.log('故事的小黄花 从出生那年就飘着')
}
}
需求:调用对象( jay )的 sing 方法,让他唱歌。
jay.sing()
说明:通过 点语法( . 就先拿到方法名称,然后,通过 小括号 调用方法。
补充说明:
console.log(参数1, 参数2, ...)
实际上, console 是一个对象,而 log 是该对象提供的一个方法。
并且, log 方法可以有多个参数。
console.log('我叫', jay.name)

总结:

通过什么符号,来访问对象中的属性或方法?
点语法( .
技巧:通过点语法,访问对象属性时,利用 VSCode 出来的提示,快速选择要访问的属性或方法。
该技巧很实用,特别是访问别人创建的对象时(比如: console 对象)。
注意:方法需要调用,所以,通过点语法拿到方法名称后,不要忘记使用小括号调用!

4.2 存值

存值,即修改(设置)对象中属性的值。
let jay = { name: '周杰伦', height: 175 }
需求:将对象( jay )的 name 属性的值修改为 ' 周董 '
jay.name = '周董'
解释:先通过点语法获取到 name 属性,然后,将新值 ' 周董 ' 赋值 给该属性。
console.log(jay.name) // 周董
注意:设置的新值,也必须符合该属性的类型要求!
注意:几乎不会修改对象中的方法。

总结:

对象是对现实生活中具体事物(特征和行为)的抽象,可以使用对象来描述这些具体的事物。
对象包含: 1 属性 2 方法。
简单来说:对象就是无序键值对的集合。
对象是结构化的,它的类型注解就是从对象的结构(属性、方法)出发,进行类型约束和检查。
推荐:使用 接口 来作为对象的类型注解, 建立一种契约,约束对象的结构。
TS 中的数据类型分为两大类: 1 原始类型(基本数据类型) 2 对象类型(复杂数据类型)。
常用的基本数据类型有 5 个: number / string / boolean / undefined / null
复杂数据类型 object (对象、数组)、 function (函数)。

五、内置对象

5.1 概述

对象的两种来源: 1 自己创建 2 其他人创建(编程语言自带或第三方)。
内置对象,是 TS/JS 自带的一些基础对象,提供了 TS 开发时所需的基础或必要的能力。
已经用过的内置对象:数组。
1. 学习内置对象,需要学什么? 常用属性和方法
2. 怎么学?  查文档

5.2 学习方式 - 查文档

注意:内置对象中提供了非常多的方法或属性,以满足开发中各种各样的需求。
编程不是死记硬背,而是掌握一定的技巧, 查文档 就是最重要的一个。
文档地址: MDN (更标准) / W3school (国内)

总结:

内置对象,是 TS/JS 自带的一些基础对象,提供了 TS 开发时所需的基础或必要的能力。
学什么?学内置对象中的属性或方法。
怎么学?查文档,文档地址: MDN (更标准) / W3school (国内)

Web 开发

一、Web 开发基础

1.1 概述

下棋游戏(XXOO)是通过 Web (网页)开发实现的,因此,我们要学习 Web 开发的相关知识。

Web 开发涵盖以下内容: HTML CSS JavaScript 
三者之间的关系:
  • (结构)HTML 负责创建页面结构。
  • (样式)CSS 负责美化页面结构(相当于化妆)。
  • (行为)JavaScript 负责让页面起来,解锁更多动效。

1.2 HTML

HTML H yper T ext M arkup L anguage ,即:超文本标记语言)负责创建页面结构。
创建第一个 HTML 步骤:
2. 快速生成 HTML 基本骨架:在文件中输入英文叹号( ! ),然后,按 tab 键。
1. 创建 a .html 文件。
3. 创建按钮标签:在 body 标签中,输入 button ,按 tab 键。
4. 打开 HTML 页面:在文件夹中找到页面文件,双击打开。
注意:页面中可见的内容,写在 body 标签中。

1.3 CSS

CSS C ascading S tyle S heets ,即:层叠样式表)负责美化页面结构。
使用 CSS 的三种方式:
1. style 属性:在 HTML 标签中,通过 style 属性 来添加样式。
<p style="color: red; font-size: 50px;">天青色等烟雨 ...</p>
2. style 标签:在 head 标签中,创建 style 标签
<style>
/* 标签选择器 */
p { color: red; }
</style>
技巧: 先通过选择器获取标签,再设置样式。
常用的 CSS 选择器:
/* 标签选择器 */
p { color: red; }
/* id 选择器 */
#txt { font-size: 50px; }
/* 类(名)选择器 –- 推荐 */
.cls { backgroud-color: pink; }
推荐:使用 类选择器 来给标签添加样式!
3. CSS 文件:创建 .css 文件,将样式放在该文件中,然后在 head 中通过 link 标签引入该文件。
<link ref="stylesheet" href="./index.css" />

总结:

作用:美化页面结构。
使用方式:
1. HTML 标签的 style 属性。
2. style 标签(在 head 标签中创建)。
3. CSS 文件(在 head 中通过 link 标签引入)。
常用的 CSS 选择器:
p { color: red; } /* 标签选择器 */
#txt { font-size: 50px; } /* id 选择器 */
.cls { backgroud-color: pink; } /* 类(名)选择器 –- 推荐 */

1.4 浏览器中使用 JavaScript

JavaScript (简称: JS ),负责让页面 起来,为页面添加动效。
使用 JS 的两种方式:
1. script 标签:在 body 标签的最后面,创建 script 标签。
注意: console.log 方法打印的内容,需要在 浏览器控制台 中查看。
打开控制台( console )的方式:在页面中点击鼠标右键,选择“检查”,切换到 Console 面板。
2. 独立 js 文件:创建 index .js 文件,在 body 标签的最后面,通过 script 标签引入。
<script src="./index.js"></script>

1.5 自动刷新浏览器

问题:每次修改页面内容后,都要手动刷新浏览器,才能看到修改后的内容。
解决方式:使用 VSCode Live Server 插件,实现 自动刷新浏览器
如何使用?
作用:监视 html 或引入的 css js 的变化,在保存文件时,该插件就会帮我们自动刷新浏览器。
注意:不再双击打开 html 页面!
使用方式:在 html 文件中,点击鼠标右键,再点击 Open with Live Server 按钮即可。
注意: html 文件所在的文件夹名称 不要包含中文 ,否则,打开页面失败,插件功能无法生效!

 

二、浏览器中运行TS

注意:浏览器中只能运行 JS 无法直接运行 TS ,因此,需要将 TS 转化为 JS 然后再运行。
浏览器中运行 TS 的步骤:
1. 使用命令 tsc index.ts ts 文件转化为 js 文件。
2. 在页面中,使用 script 标签引入生成的 js 文件(注意是 js 文件)。
<script src="./index.js"></script>
问题:每次修改 ts 文件后,都要重新运行 tsc 命令将 ts 转化为 js
解决方式:使用 tsc 命令的 监视模式
tsc --watch index.ts
解释: --watch 表示启用监视模式,只要重新保存了 ts 文件,就会自动调用 tsc ts 转化为 js

三、 DOM 操作--2步走

3.1 概述

DOM D ocument O bject M odal ):文档对象模型。
DOM 是浏览器提供的( 浏览器特有 ),专门用来 操作网页内容 的一些 JS 对象。
目的:让我们可以使用 JS/TS 代码来操作页面( HTML )内容,让页面“动”起来,从而实现 Web 开发。
HTML :超文本标记语言,用来创建网页结构。
两者的关系:浏览器根据 HTML 内容创建相应的 DOM 对象,也就是:每个 HTML 标签都有对应的 DOM 对象 。

 

学习四个常用 DOM 操作: 1 获取 DOM 元素( DOM 对象) 2 设置样式 3 设置内容 4 绑定(解绑)事件。
DOM 操作的套路(技巧): 先找人 后做事
  • 找人:获取 DOM 元素。
  •  做事:设置样式、内容、绑定(解绑)事件。
document.title = '等你下课'
比如: 将 p 标签中的内容修改为:天青色等烟雨而我在等你。
步骤: 1 获取 p 元素 2 设置内容。

总结:

DOM 是浏览器提供的( 浏览器特有 ),专门用来 操作网页内容 的一些 JS 对象(API)。
通过 DOM 操作,可以让 JS/TS 控制页面( HTML )内容,让页面“动”起来,从而实现 Web 开发。
HTML 标签和 DOM 的关系:每个 HTML 标签都有对应的 DOM 对象。
DOM 操作的套路(技巧):先找人 后做事。

3.2 获取元素

常用方法有两个:
  •  querySelector(selector) 作用:获取某一个 DOM 元素。
  • querySelectorAll(selector) 作用:同时获取多个 DOM 元素。
1. 获取一个 DOM 元素:
document.querySelector(selector)
document 对象:文档对象(整个页面),是操作页面内容的入口对象。
selector 参数:是一个 CSS 选择器(标签、类、 id 选择器等)。
作用:查询(获取)与选择器参数匹配的 DOM 元素,但是,只能获取到 第一个
推荐:使用 id 选择器(唯一)。
let title = document.querySelector('#title')
解释:获取页面中 id title DOM 元素。

类型断言

问题:调用 querySelector() 通过 id 选择器获取 DOM 元素时,拿到的元素类型都是 Element
因为无法根据 id 来确定元素的类型,所以,该方法就返回了一个 宽泛 的类型:元素(Element)类型。
不管是 h1 还是 img 都是元素。
导致新问题:无法访问 img 元素的 src 属性了。
因为: Element 类型只包含所有元素共有的属性和方法(比如: id 属性)。
解决方式:使用 类型断言 ,来手动指定 更加具体 的类型(比如,此处应该比 Element 类型更加具体)。
语法:
值 as 更具体的类型
比如:
let img = document.querySelector('#image') as HTMLImageElement
解释:我们确定 id="image" 的元素是图片元素,所以,我们将类型指定为 HTMLImageElement
技巧:通过 console.dir() 打印 DOM 元素,在属性的最后面,即可看到该元素的类型。
 
总结:
类型断言:手动指定 更加具体(精确) 的类型。
使用场景:当你比 TS 更了解某个值的类型,并且需要指定更具体的类型时。
// document.querySelector() 方法的返回值类型为: Element
// 如果是 h1 标签:
let title = document.querySelector('#title') as HTMLHeadingElement
// 如果是 img 标签:
let image = document.querySelector('#image') as HTMLImageElement
技巧:通过 console.dir() 打印 DOM 对象,来查看该元素的类型。
2. 获取多个 DOM 元素:
document.querySelectorAll(selector)
作用:获取 所有 与选择器参数匹配的 DOM 元素,返回值是一个列表。
推荐:使用 class 选择器。
示例:
let list = document.querySelectorAll('.a')
解释:获取页面中所有 class 属性包含 a 的元素。

3.3 操作文本内容

读取:
dom.innerText
设置:
dom.innerText = '等你下课'
注意:需要通过 类型断言 来指定 DOM 元素的具体类型,才可以使用 innerText 属性。
注意:设置内容时,会 覆盖原来的内容 。如何实现追加内容(比如,青花瓷 -->  青花瓷-->周杰伦)?
dom.innerText = dom.innerText + ' – 周杰伦'
// 简化
dome.innerText += ' – 周杰伦'

3.4 操作样式

两种方式:
  •  dom.style 属性:行内样式操作,可以设置每一个样式属性(比如,字体大小、文字颜色等)。
  • dom.classList 属性:类样式操作,也就是操作类名,比如,添加类名、移除类名等。
1. style 属性(行内样式)
读取:
dom.style.样式名称
设置:
dom.style.样式名称 = 样式值

说明:所有的样式名称都与 CSS 相通,但命名规则为驼峰命名法。

dom.style.fontSize = '30px'
dom.style.display = 'none'
2. classList 属性(类样式)
包含三个常用方法:添加、移除、判断是否存在。
添加:
dom.classList.add(类名1, 类名2, ...)
参数表示:要添加的类名,可以同时添加多个。
比如:
<p class="a"></p>
dom.classList.add('b', 'c') // 添加 class 样式 ==> class="a b c"
移除:
dom.classList.remove(类名1, 类名2, ...)
参数表示:要移除的类名,可以同时移除多个。
比如:
<p class="a b c"></p>
dom.classList.remove('a', 'c') // 移除 class 样式 ==> class="b"
判断类名是否存在:
let has = dom.classList.contains(类名)
参数表示:要判断存在的类名。
比如:
<p class="b"></p>
dom.classList.contains('a') // false
dom.classList.contains('b') // true

总结:

类样式( classList )的操作有三种:
// 添加
dom.classList.add('a', 'b')
// 移除
dom.classList.remove('b', 'c')
// 判断是否存在
let has = dom.classList.contains('a')

3.5 操作事件

在浏览网页时,我们经常会通过移入鼠标、点击鼠标、敲击键盘等操作,来使用网站提供的功能。
如果要让我们自己实现这样的功能,就需要通过 操作事件 来实现了。
实际上,移入鼠标、点击鼠标、敲击键盘等,都是常见的 DOM 事件。
操作事件的两个方法:
  • addEventListener 添加(绑定)事件。
  •  removeEventListener 移除(解绑)事件。

1. addEventListener 添加事件

作用:给 DOM 元素添加事件。
dom.addEventListener(事件名称, 事件处理程序)
事件名称:字符串,比如: 'click' (鼠标点击事件)、 'mouseenter' (鼠标进入事件)。
事件处理程序:回调函数,指定要实现的功能,该函数会在触发事件时调用。
示例:鼠标点击按钮,打印内容。
btn.addEventListener('click', function () {
console.log('鼠标点击事件触发了')
})
事件对象 event ),是事件处理程序(回调函数)的参数。
表示:与当前事件相关的信息,比如:事件类型( type )、触发事件的 DOM 元素( target )等。
btn.addEventListener('click', function (event) {
console.log(event.type)
// click
console.log(event.target)
// btn 元素
})

2. removeEventListener 移除事件

作用:移除给 DOM 元素添加的事件,移除后,事件就不再触发了。
dom.removeEventListener(事件名称, 事件处理程序)
事件名称:同添加事件的第一个参数。
事件处理程序: 必须要跟添加事件时的事件处理程序是同一个 ,否则无法移除!

2. removeEventListener 移除事件
正确方式:
function handleClick() {}
btn.addEventListener('click', handleClick)
btn.removeEventListener('click', handleClick)
说明:添加和移除事件时,事件处理程序是同一个,都是函数 handleClick
错误演示:
btn.addEventListener('click', function () {})
btn.removeEventListener('click', function () {})
注意:以上两个函数虽然长的一样,却是不同的函数(双胞胎,不是同一个人)。

如果事件只需要 触发一次 ,可以在添加事件时处理。
处理方式:传入第三个参数,将 once 属性设置为 true
btn.addEventListener('click', function () {}, { once: true })
once :如果值为 true ,会在触发事件后,自动将事件移除,达到只触发一次的目的。

移除事件总结:

DOM 元素的事件不再使用时,就可以通过 removeEventListener 方法移除事件。
注意: 添加和移除的事件处理程序必须是同一个 ,否则无法移除!
function handleClick() {}
btn.addEventListener('click', handleClick)
btn.removeEventListener('click', handleClick)
如果事件只需要 触发一次 ,可以在添加事件时,通过 once 属性来实现。
btn.addEventListener('click', function () {}, { once: true })

函数声明形式的事件处理程序说明

1. 可以先使用函数,再声明函数。
btn.addEventListener('click', handleClick)
function handleClick() {}
原因:函数声明在当前 ts 文件中的任意位置都有定义。
// 1 先调用函数
fn()
// 2 再声明函数
function fn() {}
2. 使用事件对象参数时,应该 指定类型注解 ,否则,访问事件对象的属性时没有任何提示。
btn.addEventListener('click', handleClick)
function handleClick(event: MouseEvent) {
console.log(event.target)
}
技巧:使用原始方式(匿名回调函数)查看参数类型。

总结:

函数声明在当前 ts 文件中的任意位置都有定义。
btn.addEventListener('click', handleClick)
function handleClick() {}
fn() // 先调用函数
function fn() {} // 再声明函数
在函数声明形式的事件处理程序中,使用事件对象时,应该指定参数类型。
btn.addEventListener('click', handleClick)
function handleClick(event: MouseEvent) {}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值