vue3+TS笔记

前言

JS缺点

  • 不适合复杂的面向对象开发的情况
  • 维护困难
  • 动态类型有安全隐患
  • 太少报错,导致后面会出现更大问题

TS

以JavaScript为基础构建的语言;一个JavaScript的超集;微软写的,解决js的问题,比如静态类型;任何支持JavaScript的平台中执行;扩展了JavaScript;TS不能被js解析器直接执行,需要ts文件进行编译转化为js文件,浏览器才可以执行。

  • 增加了类型:
    枚举。。。
  • 支持ES新特性
  • 抽象,接口

一. 基本类型

注意定义为什么类型,后期赋值的时候,只能是这个类型的数据

  • 布尔
  • 数字
  • 字符串
  • undefined和null
    可以是任何类型的子类型
  • 数组 let list1: number[] = [1,2,3] 或者 let list2: Array<number> = [1,2,3]
    定义后里面的数据类型必须和定义数组时候的类型一致
  • 元组
    要保证数据类型和个数一致
    1
    2
    3
    4
    5
    let t1: [string, number]
    t1 = ['hello', 10] // OK
    t1 = [10, 'hello'] // Error

    console.log(t1[0].substring(1)) // OKconsole.log(t1[1].substring(1)) // Error, 'number' 不存在 'substring' 方法
  • 枚举
    枚举中的元素可以是中文的数据值,但是不推荐
    1
    2
    3
    4
    5
    6
    7
    enum Color {
    Red,
    Green,
    Blue
    }

    // 枚举数值默认从0开始依次递增// 根据特定的名称得到对应的枚举数值let myColor: Color = Color.Green // 0console.log(myColor, Color.Red, Color.Blue)
  • any

我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any 类型来标记这些变量

  • void

声明一个 void 类型的变量没有什么大用,因为你只能为它赋予 undefined 和 null

  • object
    非原始类型
  • 联合类型
    表示取值可以为多种类型中的一种
    1
    2
    function toString2(x: number | string) : string {
    return x.toString()}
  • 类型断言

通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript 会假设你,程序员,已经进行了必须的检查。类型断言有两种形式。 其一是“尖括号”语法, 另一个为 as 语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14

/*
类型断言(Type Assertion): 可以用来手动指定一个值的类型
语法:
方式一: <类型>值
方式二: 值 as 类型 tsx中只能用这种方式
*/

/* 需求: 定义一个函数得到一个字符串或者数值数据的长度 */function getLength(x: number | string) {
if ((<string>x).length) {
return (x as string).length
} else {
return x.toString().length
}}console.log(getLength('abcd'), getLength(1234))
  • 类型推断
    TS会在没有明确的指定类型的时候推测出一个类型
    有下面2种情况: 1. 定义变量时赋值了, 推断为对应的类型. 2. 定义变量时没有赋值, 推断为any类型
    1
    2
    3
    4
    5
    /* 定义变量时赋值了, 推断为对应的类型 */let b9 = 123 // number// b9 = 'abc' // error

    /* 定义变量时没有赋值, 推断为any类型 */let b10 // any类型
    b10 = 123
    b10 = 'abc'

    二.接口

TypeScript 的核心原则之一是对值所具有的结构进行类型检查。我们使用接口(Interfaces)来定义对象的类型。接口是对象的状态(属性)和行为(方法)的抽象(描述)

1
2
3
4
5
6
7
8
9
10
11
// 定义人的接口interface IPerson {
id: number
name: string
age: number
sex: string}

const person1: IPerson = {
id: 1,
name: 'tom',
age: 20,
sex: '男'}
  • 可选属性
    sex?: string

可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。

  • 只读属性
    readonly id: number
    构造器中,可以对只读的属性成员进行修改
    构造器函数中的参数,一旦使用readonly进行修饰后,那么该参数叫参数属性,会自动有一个属性成员(public,private,protected同理)
    一旦赋值后再也不能被改变了。
    readonly VS const
    作为变量使用的话用const。作为属性使用readonly
    • 函数类型

接口能够描述 JavaScript 中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述函数类型。为了使用接口表示函数类型,我们需要给接口定义一个调用签名。它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
/* 
接口可以描述函数类型(参数的类型与返回的类型)
*/

interface SearchFunc {
//调用签名
(source: string, subString: string): boolean}


const mySearch: SearchFunc = function (source: string, sub: string): boolean {
return source.search(sub) > -1}

console.log(mySearch('abcd', 'bc'))
  • 一个类可以实现多个接口,一个接口也可以继承多个接口

三.类

与面向对象的语言一样

  • 继承
  • 多态
    父类型引用指向了子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为
  • 不能通过实例对象直接调用静态属性或方法,可以通过类名.的方式使用
  • 构造函数不能通过static进行修饰
  • 抽象类,抽象方法abstract
    不能实例化抽象类的对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54

    class Animal {
    name: string

    constructor (name: string) {
    this.name = name
    }

    run (distance: number=0) {
    console.log(`${this.name} run ${distance}m`)
    }

    }

    class Snake extends Animal {
    constructor (name: string) {
    // 调用父类型构造方法
    super(name)
    }

    // 重写父类型的方法
    run (distance: number=5) {
    console.log('sliding...')
    super.run(distance)
    }}

    class Horse extends Animal {
    constructor (name: string) {
    // 调用父类型构造方法
    super(name)
    }

    // 重写父类型的方法
    run (distance: number=50) {
    console.log('dashing...')
    // 调用父类型的一般方法
    super.run(distance)
    }

    xxx () {
    console.log('xxx()')
    }}

    const snake = new Snake('sn')
    snake.run()

    const horse = new Horse('ho')
    horse.run()

    // 父类型引用指向子类型的实例 ==> 多态const tom: Animal = new Horse('ho22')
    tom.run()

    /* 如果子类型没有扩展的方法, 可以让子类型引用指向父类型的实例 */const tom3: Snake = new Animal('tom3')
    tom3.run()/* 如果子类型有扩展的方法, 不能让子类型引用指向父类型的实例 */// const tom2: Horse = new Animal('tom2')// tom2.run()

    四.函数

    与面向对象的语言一致
  • 可选参数和默认参数

JavaScript 里,每个参数都是可选的,可传可不传。 没传参的时候,它的值就是 undefined。 在TypeScript 里我们可以在参数名旁使用 ? 实现可选参数的功能。
在 TypeScript 里,我们也可以为参数提供一个默认值当用户没有传递这个参数或传递的值是 undefined 时。 它们叫做有默认初始化值的参数。

  • 剩余参数

剩余参数会被当做个数不限的可选参数。 可以一个都没有,同样也可以有任意个。 编译器创建参数数组,名字是你在省略号( …)后面给定的名字,你可以在函数体内使用这个数组。

1
2
function info(x: string, ...args: string[]) {
console.log(x, args)}info('abc', 'c', 'b', 'a')
  • 函数重载
    函数名相同, 而形参不同的多个函数

    五.泛型

指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//需求:定义一个函数,传入2个参数,第一个参数是数据,第二个参数是数量
//根据数量产生对应个数的数据,存放到一个数组中  
(()=>{
    //注意:使用any的话,再对其进行split()或toFixed()操作,没用提示信息
    function getArr(x:any,n:number): number[]{
        const arr:number[] = []  
        for(let i = 0;i < n;i++){
            arr.push(x)
        }
        return arr
    }
})()

//使用泛型有提示
function getArr<T>(x:T,n:number):T[]{
        const arr:T[] = []  
        for(let i = 0;i < n;i++){
            arr.push(x)
        }
        return arr
    }  
    const arr1 = getArr<string>('123',4)
  • 泛型接口

在定义接口时, 为接口中的属性或方法定义泛型类型
在使用接口时, 再指定具体的泛型类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface IbaseCRUD <T> {
data: T[]
add: (t: T) => void
getById: (id: number) => T
}

class UserCRUD implements IbaseCRUD <User> {
data: User[] = []

add(user: User): void {
user = {...user, id: Date.now()}
this.data.push(user)
console.log('保存user', user.id)
}

getById(id: number): User {
return this.data.find(item => item.id===id)
}}
  • 泛型类
    在定义类时, 为类中的属性或方法定义泛型类型 在创建类的实例时, 再指定特定的泛型类型
    1
    2
    3
    4
    5
    6
    7
    interface Lengthwise {
    length: number;}

    // 指定泛型约束function fn2 <T extends Lengthwise>(x: T): void {
    console.log(x.length)}

    fn2('abc')// fn2(123) // error number没有length属性

    六.其他

    • 引入外部文件

当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
声明语句: 如果需要ts对新的语法进行检查, 需要要加载了对应的类型说明代码
declare var jQuery: (selector: string) => any;
声明文件: 把声明语句放到一个单独的文件(jQuery.d.ts)中, ts会自动解析到项目中所有声明文件
下载声明文件: npm install @types/jquery –save-dev

1.根文件集成终端输入npm install jquery 2.方法太多了,如果每个方法都写一个jquery.d.ts声明文件,过于繁琐。使用npm install @types/jquery –save-dev下载声明文件

  • 内置对象

JavaScript 中有很多内置对象,它们可以直接在 TypeScript 中直接使用
1.ECMAScript的内置对象

1
2
3
4
5
6
Boolean
Number
String
Date
RegExp
Error

2.BOM和DOM的内置对象

1
2
3
4
5
6
7
8
9
10
Window
Document
HTMLElement
DocumentFragment
Event
NodeList

const div: HTMLElement = document.getElementById('test')const divs: NodeList = document.querySelectorAll('div')
document.addEventListener('click', (event: MouseEvent) => {
console.dir(event.target)})const fragment: DocumentFragment = document.createDocumentFragment()

ts在vscode自动编译

  • 新建文件,在集成终端打开它,输入tsc –init,自动生成tsconfig.json文件
  • 更改tsconfig.json的配置,outDir//输出目录。strict//严格模式:false
  • 启动监视任务,终端–》任务运行–》显示所有任务
    类型注解 :是一种轻量级的为函数或者变量添加的约束

接口

是一种能力,一种约束而已

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(()=>{
interface IPerson {
firstName: string //姓氏
lastName: string //名字
}
// 输出姓名
function showFullName(person: IPerson){
return person.firstName + '_' + person.lastName
}
//定义的一个对象
const person = {
firstName: "东方",
lastName: "不败"
}
console.log(showFullName(person))
})()

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
(()=>{
interface IPerson {
firstName: string //姓氏
lastName: string //名字
}
//定义一个类型
class Person {
//定义公共的字段(属性)
firstName:string //姓氏
lastName:string //名字
fullName:string //姓名
//定义一个构造器函数
constructor (firstName:string,lastName:string){
//更新属性数
this.firstName = firstName
this.lastName = lastName
this.fullName = this.firstName + '_' +this.lastName
}
}
//定义一个函数
function showFullName(person:IPerson){
return person.firstName+'_'+person.lastName
}
//实例化函数对象
const person = new Person('诸葛','孔明')
console.log(showFullName(person))
})()

webpack打包ts

  • 建public/index.html和src/main.ts以及build/webpack.config.js
    build/webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
const {CleanWebpackPlugin} = require('clean-webpack-plugin')const HtmlWebpackPlugin = require('html-webpack-plugin')const path = require('path')

const isProd = process.env.NODE_ENV === 'production' // 是否生产环境

function resolve (dir) {
return path.resolve(__dirname, '..', dir)}

module.exports = {
mode: isProd ? 'production' : 'development',
entry: {
app: './src/main.ts'
},

output: {
path: resolve('dist'),
filename: '[name].[contenthash:8].js'
},

module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
include: [resolve('src')]
}
]
},

plugins: [
new CleanWebpackPlugin({
}),

new HtmlWebpackPlugin({
template: './public/index.html'
})
],

resolve: {
extensions: ['.ts', '.tsx', '.js']
},

devtool: isProd ? 'cheap-module-source-map' : 'cheap-module-eval-source-map',

devServer: {
host: 'localhost', // 主机名
stats: 'errors-only', // 打包日志输出输出错误信息
port: 8081,
open: true
},}
  • 终端打开根文件夹,输入npm init -y,会自动生成package.json。输入tsc –init,会自动生成tsconfig.json
  • 下载依赖
1
2
3
4
5
6
yarn add -D typescript
yarn add -D webpack webpack-cli
yarn add -D webpack-dev-server
yarn add -D html-webpack-plugin clean-webpack-plugin
yarn add -D ts-loader
yarn add -D cross-env
终端依次输入npm install -D typescript   npm install -D webpack@4.41.5webpack-cli@3.3.10 webpack-dev-server@3.10.2  npm install -D html-webpack-plugin clean-webpack-plugin  ts-loader cross-env  
  • 配置打包目录package.json
1
2
3
 scripts:{
"dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js",
"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"}
  • 运行
    npm run dev
  • 配置
    `npm run build