typescript学习笔记
目录:
typescript相比JS的优势
JS的类型系统存在“先天缺陷”,绝大部分错误都是类型错误(Uncaught TypeError)。
优势一:类型化思维方式,使得开发更加严谨,提前发现错误,减少改bug时间。
优势二:类型系统提高了代码可读性,并使维护和重构代码更加容易。
优势三:补充了接口、枚举等开发大型应用时JS缺失的功能。
为什么要安装解析JS的工具包?
Node.js/浏览器,只认识Js代码,不认识TS代码。所以需要先将TS代码转换成JS代码,然后就可以在Node.js/浏览器中运行了。
安装解析TS的工具包
安装步骤:
- 打开vscode终端。
- 输入安装命令:npm i -g typescript敲回车,来安装(需要联连网时)
typescript:就是用来解析TS的工具包。提供了tsc命令,实现了TS->JS的转化。
npm:用来安装前端开发中用到的包,是安装Node.js时自动安装的。
i(install):表示安装。
-g(-global):全局标识,可以在任意目录使用该工具。
第一个TS文件
步骤:
- 创建ts文件:
(1)在你喜欢的目录下创建文件夹:tsCode
(2)在创建的文件夹上点击鼠标右键,然后点击 Open with Visual Studio Code(用VScode打开文件夹) 将VScode添加至右键菜单
(3)在VScode中新建ts文件:hello.ts(注意:文件后缀名为:.ts) - 写代码,在hello.ts中,写入以下代码,并保存。
console.log('hello TS')
- 执行代码,分两步
(1)TS代码->JS代码,在当前目录打开终端,输入命令:tsc hello.ts敲回车 tsc hello.ts会生成一个同名文件hello.js文件
解决方案:无法加载文件 C:\Users\Administrator\AppData\Roaming\npm\tsc.ps1,因为在此系统上禁止运行脚本
(2)执行JS:输入 node hello.js(注意:后缀为.js)。
简化执行TS的步骤
由于每次修改代码后,都要重复执行两个命令才能执行TS代码,太繁琐。
(1)tsc hello.ts
(2)node hello.js
简化方式:使用 ts-node 包,“直接”在node.js中执行代码。(ts-node包内部偷偷的将TS->JS,然后执行JS代码。ts-node包提供了命令 ts-node,用来执行代码)。
安装命令:npm i -g ts-node。
总结:
数据类型:
TypeScript中的数据类型分为两大类:1.原始类型(基本数据类型)2.对象类型(复杂数据类型)
常用的基本数据类型有5个:number、string、Boolean、null、undefined。
对象类型:对象类型、数组类型、类类型、函数类型。
示例:
const xiaoJieJie: { name: string, age: number } = { name: "李思思", age: 20, }; const xiaoJieJies: string[] = ["李琪", "王美美", "邓琪琪", "王晓晓"]; class person {} const daJiao: person = new person(); const jianXiaoJieJie:()=>string=()=>{ return '大脚' }
null、undefined区别
创建对象:
TS中的对象是结构化的,结构简单来说就是对象有什么属性或方法。在使用对象前,就可以根据需求,提前设计好对象的结构。
示例:创建一个对象,里面包含姓名、年龄两个属性。
思考过程:对象的结构包含姓名、年龄两个属性;姓名->字符串类型、年龄->数值类型;创建对象。
let person:{ name:string; age:number } person={ name:'张三', age:29 }
这就是对象的结构化类型(左侧),即:对该对象值(右侧)的结构进行类型约束。
对象方法的类型注解
问题:如何给对象中的方法,添加类型注解?
技巧:鼠标放在变量名称上,vscode就会给出该变量的类型注解。
let person: { sayHi: () => void; sing: (name: string) => void; sum: (num1: number, num2: number) => number; };
箭头(=>)左边小括号中的内容:表示方法的参数类型。
箭头(=>)右边的内容,表示方法的返回值类型。
方法类型注解的关键点:1.参数。2返回值。
接口的使用
直接在对象名称后面写类型注解的坏处:1.代码结构不简洁 2.无法复用类型注解。
示例:
let p1: { name: string; age: number; sayHi: () => void; } = { name: "张三", age: 20, sayHi: function () { console.log("大家好,我叫张三,今年20岁"); }, }; let p2: { name: string; age: number; sayHi: () => void; } = { name: "李四", age: 29, sayHi: function () { console.log("大家好,我叫李四,今年29岁"); }, };
两个结构相同的p1、p2如果需要给其添加类型注解,那么就会发现结构一点也不简洁,并且有点混乱,如果有多个结构相同的对象的话,则需要把类型注解重复写多次,相同的代码重复写不太好,因此这就是第二个问题,无法复用类型注释,解决方式:用接口。
接口优势:为对象的类型注释命名,并为你的代码建立契约来约束对象的结构。
interface 就是接口的意思,其后跟的就是接口名字,名字后面就是对象的类型注解。
像上面的p1、p2其实就可以使用接口TUser的类型注解。
/* 语法: */ interface TUser { name: string; age: number; sayHi: () => void; }
p1、p2使用接口
// 使用接口 let p1: TUser = { name: "张三", age: 20, sayHi: function () { console.log("大家好,我叫张三,今年20岁"); }, }; let p2: TUser = { name: "李四", age: 29, sayHi: function () { console.log("大家好,我叫李四,今年29岁"); }, };
如果p1或p2中的值没有按接口TUser的接口的约束来赋值,则会报错
示例:
let p2: TUser = { name: "李四", age: 'ddd', sayHi: function () { console.log("大家好,我叫李四,今年29岁"); }, };
代码 age 赋值处会报红,鼠标放到age处则会有错误提示
总结:
对象是对现实生活中具体事物(特征和行为)的抽象,可以使用对象来描述这些具体的事物。
对象包含:属性;方法。
简单来说,对象就是无序键值对的集合。
对象是结构化的,它的类型注解就是从对象的结构(属性、方法)出发,进行类型约束和检查。
推荐:使用接口来作为对象的类型注解,建立一种契约,约束对象的结构。
学习:
在浏览器中运行TS
注意:在浏览器中只能运行JS,无法直接运行TS,因此,需要将TS转换为JS再运行。
浏览器中运行TS的步骤:
使用命令 tsc index.ts将TS转换为JS。
在页面中使用script标签引入生成的js文件(注意是js文件)。
<script src="index.js"></script>
示例:
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>在浏览器中运行TS</title> </head> <body> <script src="index.js"></script> </body> </html>
TS index.ts
function sum(num1: number, num2: number) { return num1 + num2; } let res = sum(1, 2); console.log(`TS代码执行了:${res}`);
问题:每次修改TS文件后,都要重新运行tsc命令将TS转化为JS。
解决方式:使用tsc命令的监视模式。
tsc --watch index.ts
解释: --watch表示启用监视模式,只要重新保存了ts文件,就会自动调用tsc将ts转化为js。
typeScript操作dom
DOM(Document ObjectModal):文档对象模型。DOM是浏览器提供的(浏览器特有),专门用来操作网页内容的一些JS对象。
目的:让我们可以使用JS/TS代码来操作页面(HTML)内容,让页面“动”起来,从而实现web开发。
HTML:超文本标记语言,用来创建网页结构。
两者的关系:浏览器根据HTML内容创建相应的DOM对象,也就是:每个HTML标签都有对应的DOM对象。
DOM操作的套路(技巧):先找人后做事。
获取一个DOM元素:
document.querySelector(selector)
作用:查询(获取)与选择器参数匹配得DOM元素,但是只能获取到第一个。
推荐:使用id选择器(唯一)。
示例:
HTML代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>获取元素——querySelector</title> </head> <body> <h1 id="title">青花瓷</h1> <p class="c1">天青色等烟雨</p> <p class="c2">而我在等你</p> <script src="index.js"></script> </body> </html>
TS代码:
// 示例:获取id为title的DOM元素 // let title = document.querySelector("#title"); // console.log(title);//<h1 id="title">青花瓷</h1> // 示例:通过标签获取DOM元素 // let p = document.querySelector("p"); // console.log(p);//<p class="c1">天青色等烟雨</p> // 示例:通过class选择器取DOM元素 let _class = document.querySelector(".c2"); console.log(_class);//<p class="c2">而我在等你</p>
类型断言
问题:调用querySelector()通过id选择器获取dom元素时,拿到的元素类型都是 Element 。无法访问元素的属性,例如:无法访问img的src属性。因为 Element 类型只包含所有元素共有的属性和方法,比如:id属性、class属性。
解决方式:使用类型断言,来手动指定 更加具体 的类型(比如,此处应该比 Element 类型更加具体)。
语法:
值 as 更具体的类型。
示例:
给上述HTML中加入:
<img src="./img/red.jpg">
TS改为:
let _img = document.querySelector("img") as HTMLImageElement; console.log(_img.src);//http://xxxx/img/red.jpg
解释:我们选择了图片标签所以确定就是图片元素,所以将类型指定为 HTMLImageElement。
技巧:通过 console.dir() 打印DOM元素,在属性的最后面,即可看到该元素的类型。
打印img后