入门
介绍:基于JS衍生,JS的超集,为限制JS的动态类型,TS为静态类型,减少项目BUG和后期维护成本
安装node.js【去官网】,安装TypeScript编译器【安装node后,命令行去全局安装TS编译器】
npm i typescript -g
命令行工具,进入ts文件目录,输入…即可将ts转js,默认编译为es3,可通过配置编译器es3~es12+
tsc 文件名.ts
变量定义
# 基本定义
let str: string = ''
let num: number
num = 18
# 简写形式,声明和赋值同时进行可以简写,默认第一次的类型
let arr = []
#声明类型,但是不会赋值
let arr: []
# js项目动态类型易出bug的地方,参数没有类型限制
# 参数类型限制,返回值类型限制
function sum(n1: number, n2: number) :number{
return n1 + n2
}
# 限制变量在两个值之间选择,以此类推
let str : 'str1' | 'str2'
# 限制变量的类型,只能在两个类型之间选择,以此类推
let str : number | srring
# any 表示任意类型,声明不指定默认为any,可以赋值给其他已定义类型的变量
let str: any
let sty
# unknown 表示未知的类型,不可以赋值给其他已定义类型的变量,推荐使用unknown代替any
let str: unknown
sty = 18
sty = 'str'
# 类型断言,可配合unknown使用,告知解析器变量的实际类型
let num: number
num = str as number
num = <number>str
# void 表示空,在函数返回值中,限制返回值为undefined、null或者无返回值
function fun(): void{ return undefined }
# never 在函数中,表示没有返回值,如用于代码报错
function fun(): never{ }
声明对象
# 声明对象,obj对象的赋值1、name必须赋值;2、age?表示可以不写;3、有且仅有name和age【可不写】
let obj: {name: string, age?: number}
obj = {name: '名字'}
# 上一种写法限制了属性的数量和属性值的类型
# obj对象的赋值1、name必须赋值;2、多个任意属性名,任意类型属性值
let obj: {nzme :string, [otherName: string]: any}
obj = {name: '名字', age: 18, gender: '男'}
声明函数
# 声明函数对象的参数类型、数量和返回值的类型,给函数对象赋值的时候就可省略声明,但是要确保赋值要和声明对应
let fun: (num1: number, num2: number) => number
fun = function (n1, n2) return n1+n2
声明数组
# 声明string类型数组,数组存放的值只能是string类型的
let arr: string[]
# 声明number类型的数组
let arr: Array<number>
# 【元祖】:固定长度的数组,性能更好
let tup: [string, number]
tup = ['str', 18]
enum枚举【TS新增】
# enum使用场景:性别等属性的赋值,属性值具有数量少,值固定的特点
enum Gender{
Male = 0,
Famale = 1
}
let fun: {name: string, gender: Gender}
fun = {
name: '名字',
gender: Gender.Male
}
type类型别名【TS新增】
# type使用场景:类似于封装,简化代码
let num1 = 1 | 2 | 3 | 4
let num2 = 1 | 2 | 3 | 4
||
||
type myType = 1 | 2 | 3 | 4
let num1 = myType
let num2 = myType
类型 | 例子 | 描述 |
---|---|---|
number | 1, -33, 2.5 | 任意数字 |
string | ‘hi’, “hi” | 任意字符串 |
boolean | true、false | 布尔值true或false |
字面量 | 其本身 | 限制变量的值就是该字面量的值 |
any | * | 任意类型 |
unknown | * | 类型安全的any |
void | 空值(undefined) | 没有值(或undefined) |
never | 没有值 | 不能是任何值 |
object | { name: ‘孙悟空’ } | 任意的JS对象 |
array | [ 1, 2, 3 ] | 任意JS数组 |
tuple | [ 4, 5 ] | 元素,TS新增类型,固定长度数组 |
enum | enum { A, B } | 枚举,TS中新增类型 |
编译
监视单文
控制台 —— 当前目录下 ——【 tsc 文件名.ts
】
监视多文件
新建【tsconfig.json】文件
【tsc
】编译所有文件,【tsc -w
】监视所有文件
配置【tsconfig.json】
- 常规属性
{
// 定义被编译文件所在的目录;【**】表示任意目录,【*】表示任意文件
"include":["src/**/*", "tests/**/*"],
// 定义需要排除在外的目录
"exclude": ["./src/module/**/*"],
// 定义被继承的配置
"extends": "./configs/base",
// 指定被编译文件的列表,编译的文件少时才会使用
"files": [ "core.ts", "sys.ts" ],
// 指定各种编译规范和编译模式
compilerOptions: {
// 设置ts编译js的目标版本 es2015 == es6,为了兼容可以编译es5
"target": "ES6",
// 设置编译后代码使用的模块化系统
"module": "CommonJS",
// 指定代码运行时所包含的库(宿主环境),一般不写这不配置,ts编译器默认采用内置的
"lib": ["ES6", "DOM"],
// 【outDir】 指定编译后文件的存放目录
// 【outFile】 合并编译后的js文件,指定名称
// 使用模块,指定【'module': 'system' | 'None' | 'AMD'】才能使用,二者结合打包工具使用
"outDir": "dist",
"outFile": "dist/xx.js",
// 【allowJs】是否编译js文件,【checkJs】是否检查js文件语法规范,默认都为flase,搭配使用
"allowJs": false,
"checkJs": false,
// 是否删除编译后文件的注释,默认false
"removeComments": true,
// 不生成编译后的文件,一般做ts语法检查时使用
"noEmit": false,
// ts存在错误,不进行编译
"noEmitOnError": true
}
}
- 常用语法检查属性
{
// 指定各种编译规范和编译模式
compilerOptions: {
//所有严格检查的总开关,开启之后,下方的严格检查自动开启,建议开启,减少项目后期可能出现的bug
"strict" : true
//用来设置编译后的文件是否使用严格模式,默认false
"alwaysStrict" : true,
//不允许隐式的any类型
"noImplicitAny " : true,
//不允许不明确类型的this,如普通函数中的【this】
"noImplicitThis" : true,
//严格的检查空值
"strictNullChecks" : true,
}
}
- 非常用语法检查属性
- strictBindCallApply:严格检查bind、call和apply的参数列表
- strictFunctionTypes:严格检查函数的类型
- strictNullChecks:严格的空值检查
- strictPropertyInitialization:严格检查属性是否初始化
- noFallthroughCasesInSwitch:检查switch语句包含正确的break
- noImplicitReturns:检查函数没有隐式的返回值
- noUnusedLocals:检查未使用的局部变量
- noUnusedParameters:检查未使用的参数
- allowUnreachableCode:检查不可达代码
- noEmitOnError:有错误的情况下不进行编译
结合webpack
初始化【package.json】,管理项目
npm init -y
安装Webpack、TypeScript相关库
cnpm i -D
webpack webpack-cli webpack-dev-server typescript ts-loader clean-webpack-plugin
@babel/core @babel/preset-env babel-loader core-js
-
webpack:构建工具webpack
-
webpack-cli:webpack的命令行工具
-
webpack-dev-server:webpack的开发服务器
-
typescript:ts编译器
-
ts-loader:ts加载器,用于在webpack中编译ts文件
-
html-webpack-plugin:webpack中html插件,用来自动创建html文件
-
clean-webpack-plugin:webpack中的清除插件,每次构建都会先清除目录
-
@babel/core:babel的核心工具
-
@babel/preset-env:babel的预定义环境
-
@babel-loader:babel在webpack中的加载器
-
core-js:core-js用来使老版本的浏览器支持新版ES语法
新建【tsconfig.json】
新建【webpack.config.js】
修改【package.json】
{
"script":{
"build": "webpack"
}
}
新建【babel】
面向对象
介绍:js将程序抽象成一个对象,这个对象又包含多个小对象,程序之中所有的操作都需要通过对象来完成,一切操作都要通过对象,也就是所谓的面向对象
- 操作浏览器要使用window对象
- 操作网页要使用document对象
在程序中所有的对象都被分成了两个部分:数据和功能
以人为例,人的姓名、性别、年龄、身高、体重等属于数据,人可以说话、走路、吃饭、睡觉这些属于人的功能
面向对象和面向过程
- 面向对象可以看做是对象的封装【模块化】,将对象相关的方法和属性写入类中,不同的类为单独的TS文件,最后将所有类引入到【控制器类】中,项目越大,后期效果越好
- 面向过程是对程序的每一步进行操作,将所有方法写到流程中,项目较小时可以使用
类 Class
对象:原对象和自定义对象。要想对对象进行各种操作,那就得赋予它各种属性,让它具备完成操作的能力
如何创建一个能完成各种操作的对象,要创建对象,必须要先定义类
类(class):对象的模型,程序中根据这个对象的模型,创建指定类型的对象,不同的模型创建不同的对象
-
定义类
class Person{ }
-
使用类实例化对象
const person = new Person
类的属性和方法
- 实例属性、静态属性(类属性static),实例属性通过实例对象访问,静态属性通过对象访问
- 例属性的值可以通过实例来修改,如果被【readonly】修饰,只可读
- 类中的属性存在自动类型判断
- 类中的方法也是如此,实例方法、静态方法、static修饰、readonly修饰、自动类型判断
class Person{
name: string = '孙悟空'
static age: number =18
readonly gender: string = '男'
height = 168
eat(){ }
}
let per = new Person()
per.name === '孙悟空'
Person.age === 18
类的构造函数 Constructor
【constructor】类实例化的时候都会被调用,用于实例不同的对象,
class Person{
name: string;
age: number;
constructor(name: string, age: number){
this.name = name;
this.age = age;
}
sayHello(){
console.log this.name
}
}
const person1 = new Person('孙悟空', 18);
const person2 = new Person('猪八戒', 18);
类的继承 Extends
不同的类之间,可能会存在相同的属性,当相同属性较多时可以封装成父类,子类通过继承获取父类的属性
class Animal{
name: string;
constructor(name: string){
this.name = name;
}
run(){ console.log('父类中的run方法!') }
}
class Dog extends Animal{
bark() { console.log(`子类中的bark方法`) }
run() { console.log(`子类中的run方法,会重写父类中的run方法!`) }
}
const dog = new Dog('旺财');
类的父类 Super
super在子类中,表示当前的父类
class Animal{
name: string;
constructor(name: string){
this.name = name;
}
}
class Dog extends Animal{
constructor(name: string, age: number) {
//子类中写了构造函数,构造函数中必须调用super(),否则父类的构造函数会被重写,继承失败
super(name);
this.age = age;
}
}
const dog = new Dog('旺财', 3);
类的属性修饰符
- public(默认值),可以在父类、子类、对象中修改
- private ,私有属性,可以在父类中修改
- 在JS中,对象可以直接修改父类属性的值,这使得数据的安全性大大降低。属性设置private修饰,只能通过调用父类中的方法,去修改父类属性的值,属性的修改和读取由父类的方法控制,称为数据的存取器
- 使用场景:当该属性的容易被修改错或是对计算要求比较高或是比较重要时,可在存取器的set()设置判断
- protected ,受保护的属性,可以在父类、子类中修改
class test(){
name: string
constructor(name:string){ }
}
简写
class test(){
constructor(public name:string){ }
}
抽象类 Abstract
抽象类是专门用来被其他类所继承的类,它只能被其他类所继承不能用来创建实例
abstract开头的方法叫做抽象方法,抽象方法没有方法体,只能定义在抽象类中,继承抽象类时抽象方法必须要实现
abstract class Animal{
abstract run(): void;
bark(){
console.log('');
}
}
class Dog extends Animals{
run(){
console.log('');
}
}
接口 Interface
接口的作用类似于抽象类,不同点在于接口中的所有方法和属性都是没有实值的,接口中的所有方法都是抽象方法
接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口
interface Person{
name: string;
sayHello():void;
}
function fn(per: Person){
per.sayHello();
}
fn({
name:'孙悟空',
sayHello() { console.log( this.name ) }
});
让一个类去实现接口,类中要包括接口中的所有属性
interface Person{
name: string;
sayHello():void;
}
class Student implements Person{
constructor(public name: string) { }
sayHello() { console.log( this.name ) }
}
泛型 Generic
定义一个函数或类时,有些情况下无法确定其中要使用的具体类型(返回值、参数、属性的类型不能确定),此时泛型便能够发挥作用
-
使用泛型之前,通过【any】,会关闭TS语法检查
function test(arg: any): any{ return arg }
-
使用泛型之后,【<>】中为任意字母
function test<T, K>(a: T, b: K): K{ return b } //不指定泛型,TS会自行推断,个别情况无法推断 test(10, "hello") //指定泛型,推荐 test<number, string>(10, "hello");
-
在类中使用
class test<T>{ prop: T constructor(prop: T){ this.prop = prop } } const test1 = new test<string> ( name: '孙悟空');
-
对泛型范围进行约束,表示泛型T必须是MyInter的子类,test中的a对象实现,必须具有length属性
interface MyInter{ length: number } function test<T extends MyInter>(a: T): number{ return a.length }
类型断言
在TS中,【!】表示对一个变量断言其非空,【as】用来限制child的类型,存在类型断言时【!】可不写
head : HTMLElement
test() { this.head = document.querySelector( selectors: '#box')! as HTMLElement }
练习
- 纸上得来终觉浅,做一个TS项目实战,做一下笔记,巩固知识
其他
-
js开启严格模式,可以在代码首行添加【“use strict”】,性能更好,一般不单独开启,采用工具批量添加,js引入模块时,该文件自动开启严格模式
-
【webpack.config.js】执行【loader】的顺序是从数组的下往上执行
-
编译流程:编译执行——TS文件——tsloder(转JS)——bable(转ES5)
-
【webpack】打包会自带一个箭头函数,不经过bable的编译,编辑【webpack.config.js】
{ module.exports = { output: { enviroument:{ arrowFunction: false } } } }
-
在webstorm中,【cnpm i】安装依赖,是镜像服务器提供的文件,文件相对较多,下载完会有点乱,网络好推荐用【npm i】,VS中推荐【cnpm i】,速度快
-
CSS3在低版本浏览器中不兼容,【webpack.json】通过【postcss postcss-loader postcss-preset-env】,【loader】处理顺序从下到上
{ test: /.less$/, use: [ //将CSS引入项目,加载CSS,postcss处理CSS3兼容,less转css "style-loader", "css-loader", { loader: "postcss-loader", options: { postcssOptions : { plugins: [ [ "postcss-preset-env", { browsers: 'last 2 versions' } ] ] } } }, "less-loader" } }
-
【document.querySelectorAll】能获取所有元素,但是个数限制第一次获取的数量
【document.getElement】则不会
-
事件绑定的【this】指向,【.bind(this)】可以将函数的【this】指向改为原函数,而不是调用者
const direction: KeyboardEvent; document.addEventListener( type: 'keydown', this.test.bind(this) ); test(event: KeyboardEvent){ this.direction = event.key }