一、TypeScript 简介


1、什么是 TypeScript?

官方文档

TypeScript 本质上是向 JavaScript 语言添加了「可选的静态类型」和「基于类的面向对象」编程,它相当于是JavaScript的超集

2、为什么选择 TypeScript?

TypeScript 增加了代码的可读性和可维护性

类型系统实际上是最好的文档,大部分的函数看看类型的定义就可以知道如何使用了

可以在编译阶段就发现大部分错误,这总比在运行时候出错好

增强了编辑器和 IDE 的功能,包括代码补全、接口提示、跳转到定义、代码重构等

TypeScript 非常包容

TypeScript 是 JavaScript 的超集,.js 文件可以直接重命名为 .ts 即可

即使不显式的定义类型,也能够自动做出类型推论

TypeScript 的类型系统是图灵完备的,可以定义从简单到复杂的几乎一切类型

即使 TypeScript 编译报错,也可以生成 JavaScript 文件

兼容第三方库,即使第三方库不是用 TypeScript 写的,也可以编写单独的类型文件供 TypeScript 读取

TypeScript 拥有活跃的社区

大部分第三方库都有提供给 TypeScript 的类型定义文件

Angular、Vue、VS Code、Ant Design 等等耳熟能详的项目都是使用 TypeScript 编写的

TypeScript 拥抱了 ES6 规范,支持 ESNext 草案中处于第三阶状态(Stage 3)的特性

TypeScript 的弊端

有一定的学习成本,需要理解接口(Interfaces)、泛型(Generics)、类(Classes)、枚举类型(Enums)等前端工程师可能不是很熟悉的概念

短期可能会增加一些开发成本,毕竟要多写一些类型的定义,不过对于一个需要长期维护的项目,TypeScript 能够减少其维护成本

集成到构建流程需要一些工作量

可能和一些库结合的不是很完美

3、TypeScript 语法特性

TypeScript 是一种给 JavaScript 添加特性的语言扩展。增加的功能包括:

类型批注(注解)和编译时类型检查 type annotation

类型推断 type inferrence

接口 interface + implements

枚举 enum

Mixins

泛型编程 <>

名字空间 namespace

元组 Tupe

Async / Await

以下功能是从 ECMA 2015 反向移植而来:

类 class

extends 继承类 or 抽象类

implements 继承 接口

constructor 构造函数

super 调用父类属性

public 公共属性方法

private 私有属性方法

protected 保护属性方法

readyonly 只读属性方法

static 静态属性方法

get getter 存取器

set setter 存取器

new 实例化对象

abstract 抽象类

类 class 的本质构造函数

模块 module

lambda 函数箭头

可选参数以及默认参数

4、TypeScript 数据类型

数据类型

关键字

描述

任意类型

any

声明为 any 的变量可以赋予任意类型的值。

数字类型

number

双精度 64 位浮点值。它可以用来表示整数和分数。

字符串类型

string

使用单引号「''」或双引号「""」来表示字符串类型反引号;「 `` 」来定义多行文本和内嵌表达式。

布尔类型

boolean

表示逻辑值:true 和 false

数组类型

声明变量为数组

元组

元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同

枚举

enum

枚举类型用于定义数值集合

void

void

用于标识方法返回值的类型,表示该方法没有返回值

null

null

表示对象值缺失。

undefined

undefined

用于初始化变量为一个未定义的值

never

never

never 是其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。

注意:TypeScript 和 JavaScript 没有整数类型

5、TypeScript 安装使用

全局安装 TypeScript,使用 tsc 命令编译成 JavaScript 代码

# 注意全局安装 npm 包,一定要有对应的 操作权限
sudo npm i typescript ts -g
yarn global add typescriptmkdir ts demo// demo.ts
function sayHi():void {let web: string = "Hello World";console.log(web);
}
sayHi();
tsc demo.ts

使用 ts-node 插件直接编译运行 ts 文件

npm install -g ts-node
ts-node Demo1.ts

二、TypeScript 类型的概念和使用


1、基础静态类型和对象类型

在 TypeScript 类型分为两种,一种是基础静态类型,一种是对象类型

基础静态类型

基础静态类型非常简单,只要在声明变量的后边加一个:号,然后加上对应的类型。比如下面的代码,就是声明了一个数字类型的变量,叫做count。

const count : number=88;
const myName:string='蜡笔小新'

类似这样常用的基础类型还有,null,undefind,symbol,boolean,void

对象类型

经典对象类型,也是最简单的对象类型,如下:

const lbxx: {name: stringage: number
} = {name: "蜡笔小新",age: 18,
};
console.log(lbxx.name);

对象类型也可以是数组,如下:

const users: String[] = ["蜡笔小新", "犬夜叉", "樱桃小丸子"];

对象类型也可以是类,如下:

class Person { }
// lbxx 必须是一个 Person 实例化的对象
const lbxx: Person=new Person();

对象类型可以是函数类型,并确定返回值,如下:

const getName: () => string = () => {return "蜡笔小新";
};

总结:对象类型形式

对象类型

数组类型

类类型

函数类型

2、类型注解和类型推断

type annotation 类型注解

前面我们学到的基础静态类型和对象类型的这种约束规则就叫做 「类型注解」,如下:

// 显示的告诉代码,我们的`count`变量就是一个数字类型,这就叫做`类型注解`
let count: number;
count=123;

type inferrence 类型推断

通过初始化设置值后,系统会 自动推断属性的类型,并且不允许随意变动,这就是「类型推断」

// TypeScript 自动把变量注释为了`number`(数字)类型
let countInference=123;

工作使用问题(潜规则)

如果 TS 能够自动分析变量类型, 我们就什么也不需要做了

如果 TS 无法分析变量类型的话, 我们就需要使用类型注解

先来看一个不用写类型注解的例子:

const one=1;
const two=2;
const three=one+two;

再来看一个用写类型注解的例子:

function getTotal(one, two) {return one+two;
}
const total=getTotal(1, 2);

这种形式,就需要用到类型注释了,因为这里的one和two会显示为any类型。这时候如果你传字符串,你的业务逻辑就是错误的,所以你必须加一个类型注解,把上面的代码写成下面的样子。

function getTotal(one: number, two: number) {returnone+two;
}consttotal=getTotal(1, 2);

在写 TypeScript 代码的一个重要宗旨就是每个变量,每个对象的属性类型都应该是固定的,如果你推断就让它推断,推断不出来的时候你要进行注释。

3、函数参数和返回类型注解

简单类型注解

function getTotal(one: number, two: number) {return one+two;
}
const total=getTotal(1, 2);

我们并没有定义getTotal的返回值类型,虽然TypeScript可以自己推断出返回值是number类型, 但是如果这时候我们的代码写错了,比如:

function getTotal(one: number, two: number) {return one+two+"";
}const total=getTotal(1, 2);

这时候total的值就不是number类型了,但是不会报错,我们给返回值设置静态属性,如下:

const total: number=getTotal(1, 2);

这样写虽然可以让编辑器报错,但是这还不是很高明的算法,因为你没有找到错误的根本,这时错误的根本是getTotal()函数的错误,所以合适的做法是给函数的返回值加上类型注解,代码如下:

function getTotal(one: number, two: number): number {return one+two;
}
const total=getTotal(1, 2);

函数无返回值时定义方法

没有返回值的函数,我们就可以给他一个类型注解void,代表没有任何返回值

function sayHello(): void {console.log("hello world");
}

never 返回值类型

如果一个函数是永远也执行不完的,就可以定义返回值为never,比如执行的时候,抛出了异常,这时候就无法执行完了,如下:

function errorFuntion(): never {throw new Error();console.log("Hello World");
}

还有一种就是死循环,如下:

function forNever(): never {while (true) {}console.log("Hello JSPang");
}

函数参数为对象(解构)时使用类型注解

function add({ one, two }: { one: number, two: number }): number {return one+two;
}
const three=add({ one: 1, two: 2 });

4、数组类型的定义

单一数据类型数组的定义

const numberArr= [1, 2, 3];

TypeScript 会通过类型推断自己推断类型注解,当然也可以显式地声明数组类型注解

const numberArr: number[] = [1, 2, 3];
const stringArr: string[] = ["a", "b", "c"];
const undefinedArr: undefined[] = [undefined, undefined];

多种数据类型数组类型注解

const arr: (number|string)[] = [1, "string", 2];

数组中对象类型的定义

const users: { name: string, age: number }[] = [{ name: "蜡笔小新", age: 18 },{ name: "犬夜叉", age: 28 },
];

这种形式阅读麻烦,并且不便于复用,所有 TypeScript 为我们准备了一个概念,叫做类型别名「type alias」

type User= { name: string, age: Number };
const users: User[] = [{ name: "蜡笔小新", age: 18 },{ name: "犬夜叉", age: 28 },
];

当然我们也可以使用类来作为类型注解约束

class User {name: string;age: number;
}
const users: User[] = [{ name: "蜡笔小新", age: 18 },{ name: "犬夜叉", age: 28 },
];

5、interface 接口的使用

我们可以把这重复使用的类型注解,定义成统一的接口,比如:

interface User {name: string;age: number;
}

接口和类型别名的区别

类型别名 type 可以直接给类型,也可以给对象类型,如下:

type User=string;
const lbxx: User='蜡笔小新';

接口 interface 必须代表对象,如下:

interface User {name: string;age: number;
}
const users: User={ name: "蜡笔小新", age: 18 }

接口非必选值得定义

:号前加一个? 代表当前接口属性是非必选项

interface User {name: string;age: number;like?: string;
}

允许加入任意值

interface User {name: string;age: number;like?: string;[propname: string]: any;
}

这个的意思是,属性的名字是字符串类型,属性的值可以是任何类型

接口里的方法

接口里不仅可以存属性,还可以存方法,比如:

interface User {name: string;age: number;like?: string;[propname: string]: any;// 需要注意的是:加了方法后作为类型注解使用时对象必须要有该方法say(): string;
}

接口和类的约束

类可以和接口很好的结合,比如:

class Teacher implements User {name="蜡笔小新";age=18;say() {return"你好,我是蜡笔小新!";}
}

接口间的继承

接口也可以用于继承的,比如你新写一个Admin接口,继承于User接口。

interface Admin extends User {admin(): string;
}// 用接口直接约束对象
const qyx: Admin= {name: "黑猫警长",age: 18,say() {return"你好,我是黑猫警长!";},admin() {return"我是一个管理员";},
}

6、联合类型和类型保护

联合类型展示

所谓联合类型,可以认为一个变量可能有两种或两种以上的类型,关键符号是|竖线

class MathTeacher {public compute(): void {console.log('数学老师会计算')}
}
class EnglishTeacher {public say(): void {console.log('英语老师说 Hello!')}
}
function teacherTeach(teacher: MathTeacher|EnglishTeacher): void {}
const lucy=new MathTeacher('Lucy', '乡村小学')
// 这个时候,teacherTeach 这个方法是如何判定 lucy 对象是数学老师还是 英语老师呢?
teacherTeach(lucy)

类型保护 - 类型断言

直接调用联合类型的方法提示异常,因为 teacherTeach 方法不能准确的判断联合类型的具体实例是什么

class MathTeacher {public compute(): void {console.log('数学老师会计算')}
}
class EnglishTeacher {public say(): void {console.log('英语老师说 Hello!')}
}
function teacherTeach(teacher: MathTeacher|EnglishTeacher): void {// teacher.say() // teacher.compute()
}
const lucy=new MathTeacher('Lucy', '乡村小学')
teacherTeach(lucy)

这时候就需要再引出一个概念叫做类型保护,类型断言就是通过断言的方式确定传递过来的准确值

class MathTeacher {public compute(): void {console.log('数学老师会计算')}
}
class EnglishTeacher {public say(): void {console.log('英语老师说 Hello!')}
}
function teacherTeach(teacher: MathTeacher|EnglishTeacher): void {(teacher as EnglishTeacher).say();(teacher as MathTeacher).compute();
}
const lucy=new MathTeacher()
teacherTeach(lucy)

类型保护 - in 语法

class MathTeacher {public compute(): void {console.log('数学老师会计算')}
}
class EnglishTeacher {public say(): void {console.log('英语老师说 Hello!')}
}
function teacherTeach(teacher: MathTeacher|EnglishTeacher): void {if ("compute" in teacher) {teacher.compute()} else {teacher.say()}
}
const lucy=new MathTeacher('Lucy', '乡村小学')
teacherTeach(lucy)

类型保护 - instanceof 语法

class MathTeacher {public compute(): void {console.log('数学老师会计算')}
}
class EnglishTeacher {public say(): void {console.log('英语老师说 Hello!')}
}
function teacherTeach(teacher: MathTeacher|EnglishTeacher): void {if (teacher instanceof MathTeacher) {teacher.compute()} else {teacher.say()}
}
const lucy=new MathTeacher('Lucy', '乡村小学')
teacherTeach(lucy)

7、Enum 枚举类型

使用枚举我们可以定义一些带名字的常量,使用枚举可以清晰地表达意图或创建一组有区别的用例, TypeScript支持数字的和基于字符串的枚举。

// 数字枚举
enum Direction {Up=1, // 设置初始增长的值 后面递增 +1Down,Left,Right
}
// 字符串枚举
enum Direction {Up="UP",Down="DOWN",Left="LEFT",Right="RIGHT",
}

三、TypeScript 泛型的概念和使用


1、泛型基础使用

泛型的基础使用

泛型:[generic - 通用、泛指的意思],那最简单的理解,泛型就是泛指的类型。

泛型的定义使用<>(尖角号)进行定义的,尖括号内定义参数就是泛型名称,然后在正式调用的时候使用这个名词即可,我们一般使用 <T> 作为泛型使用

function join<T>(first: T, second: T) {return `${first}${second}`;
}
join<string>("蜡笔小新", "樱桃小丸子");

如果要是number类型,就直接在调用方法的时候进行更改就可以了

join<number>(1, 2);

泛型中数组的使用

如果传递过来的值要求是数字,如何用泛型进行定义那?

两种方法,第一种是直接使用[],第二种是使用Array<泛型>。

形式不一样,其他的都一样。

第一种写法:

function myFun<T>(params: T[]) {return params;
}
myFun<string>(["123", "456"]);

第二种写法:

function myFun<ANY>(params: Array<ANY>) {
return params;
}
myFun<string>(["123", "456"]);

在工作中,我们经常使用<T>来作泛型的表示,当然这不是硬性的规定,只是大部分程序员的习惯性写法。

多个泛型的定义

一个函数可以定义多个泛型,比如第一个泛型用T,第二个用P代表

function join<T, P>(first: T, second: P) {return `${first}${second}`;
}
join<number, string>(1, "2");

泛型的类型推断

泛型也是支持类型推断的,比如下面的代码就是类型推断的功劳。

function join<T, P>(first: T, second: P) {return `${first}${second}`;
}
join(1, "2")

但个人不建议大量使用类型推断,这会让你的代码易读和健壮性都会下降

2、泛型在类中的使用

初始类的泛型

基础一个类代码

class SelectTeacher {constructor(privateteachers: string[] |number[]) {}getOneTeacher(index: number): string|number {return this.teachers[index];}
}

使用泛型重构代码

class SelectTeacher<T> {
constructor(privateteachers: T[]) {}
getOneTeacher(index: number): T {return this.teachers[index];}
}
const teachers=new SelectTeacher(["蜡笔小新", "樱桃小丸子", "犬夜叉"]);
console.log(teachers.getOneTeacher(1))
const teachers = new SelectTeacher<string>(["蜡笔小新", "樱桃小丸子", "犬夜叉"])

泛型中的继承

定义一个 Teacher 接口

interface Teacher {
name: string;
age: number;
}

使用extends关键字实现泛型继承

interface Teacher {
name: string;
age: number;
}
class SelectTeacher<T extends Teacher> {
constructor(privateteachers: T[]) {}
getOneTeacher(index: number): T {return this.teachers[index];}
}
const teachers=new SelectTeacher([{
name: "蜡笔小新",
age: 18
},{
name: "樱桃小丸子",
age: 28
}])
console.log(teachers.getOneTeacher(0))

泛型约束

泛型可以是任意类型,可以是对象、字符串、布尔、数字都是可以的,如果我们约束泛型为指定的类型,这就叫做泛型约束

interface Teacher {
name: string;
age: number;
}
class SelectTeacher<T extends number|string> {constructor(private teachers: T[]) {}getOneTeacher(index: number): T {return this.teachers[index]}
}
const teachers = new SelectTeacher<string>(["蜡笔小新", "樱桃小丸子", "犬夜叉"])
console.log(teachers.getOneTeacher(1))

四、TypeScript 中类的概念和使用


1、类的基本使用

类的基本使用

class Person {content = "Hi,老铁";sayHello () {
return this.content;}
}
const lbxx = new Person();
console.dir(Person.prototype.sayHello.call(lbxx));//"Hi,老铁"

类的继承

class Person {content="Hi,老铁";sayHello() {return this.content;}
}
class Teacher extends Person {teach() {return"我是一个老师,当然也是一个正常人!";}
}
const lbxx=new Teacher();
console.log(lbxx.sayHello());
console.log(lbxx.teach());

类的重写

class Person {content="Hi,老铁";sayHello() {return this.content;}teach() {return "我是一个正常人,我能教点什么吗?";}
}
class Teacher extends Person {teach() {return"我成为了一个老师,当然可以教点啥了!";}
}
const lbxx=new Teacher();
console.log(lbxx.teach()); 

super 关键字的使用

class Person {content="Hi,老铁";teach() {return"我是一个正常人,想成为一个老师!";}
}
class Teacher extends Person {teach() {return super.content+super.teach() +"我成为了一个老师,当然可以教点啥了!";}
}
const lbxx=new Teacher();
console.log(lbxx.teach()); 

2、类的访问类型

public 访问属性

public从英文字面的解释就是公共的或者说是公众的,在程序里的意思就是允许在类的内部和外部被调用,public 也是类中默认的访问属性

class Person {public name:string;
}

private 访问属性

private 访问属性的意思是,只允许再类的内部被调用,外部不允许调用

class Person {private name:string;public sayHello(){console.log(this.name+'say Hello')  //此处不报错}
}
//-------以下属于类的外部--------
const person=new Person()
person.name='蜡笔小新'    //此处报错
person.sayHello()
console.log(person.name)  //此处报错

protected 访问属性

protected 允许在类内及继承的子类中使用

class Person {protected name:string;public sayHello(){console.log(this.name+'say Hello')}
}
class Teacher extends Person{public sayBye(){this.name;}
}

readonly 只读属性

class Person {public readonly_name :string;constructor(name:string ){this._name=name;}
}const person=new Person('蜡笔小新')
person._name='樱桃小丸子'// 报错,`_name`属性是只读属性,不能修改
console.log(person._name)

static 静态属性

static声明的属性和方法,不需要进行声明对象,就可以直接使用

class Girl {static sayLove() {return "I Love you";}
}
console.log(Girl.sayLove());

3、构造函数

构造函数的关键字是constructor

class Person{public name :string ;constructor(name:string){this.name=name}}
const person=new Person('蜡笔小新')
console.log(person.name)

如果属性直接匹配使用,则可以进行简写

class Person{constructor(public name:string){}
}const person=new Person('樱桃小丸子')
console.log(person.name)

类继承中的构造器写法

在子类中使用构造函数需要用super()调用父类的构造函数,子类继承父类并有构造函数的原则,就是在子类里写构造函数时,必须用super()调用父类的构造函数,如果需要传值,也必须进行传值操作

class Person{constructor(public name:string){}
}
class Teacher extends Person{constructor(name:string, public age:number){super(name)}
}
const teacher=new Teacher('樱桃小丸子',18)
console.log(teacher.age)
console.log(teacher.name)

4、类的 Getter 和 Setter

对私有属性 private 的外部访问,需要使用 Getter

class User {constructor(private_age:number){}getage(){return '年龄保密'}
}
const lbxx=new User(21)
console.log(lbxx.age)
对私有属性 private 的外部加工,需要使用 Setterclass User {constructor(private_age: number) { }// 外部访问会主动调用getage(){return this._age+18}// 内部访问会主动调用setage( age:number ){this._age = age + 18}
}const lbxx=new User(28)
console.log(lbxx.age)
// 在外部设置 年龄 ,将调整逻辑写在外面
lbxx.age=88
console.log(lbxx.age)

5、abstract 抽象类使用

抽象类的关键词是abstract,里边的抽象方法也是abstract开头的,抽象方法需要在被继承的类中被覆盖重写,并且必须包含这个抽象方法,代表的是一种约束

abstract class Teacher {constructor(publicname:string, publicschool:string) {}public abstract skill():void}class MathTeacher extends Teacher {skill() {console.log('数学老师教数学!')}public compute(): void {console.log('数学老师会计算')}
}class EnglishTeacher extends Teacher {skill() {console.log('English Teacher taech English ! ')}public say(): void {console.log('英语老师说 Hello!')}
}
const lucy=new MathTeacher('Lucy', '乡村小学')
lucy.skill()

我希望通过这个例子,你能对抽象类和抽象方法有一个比较深的认识。其实在工作中我们也会把这样的需求用接口来实现。

五、配置文件 tsconfig.json 使用(了解)


1、配置文件基础使用

tsconfig.json 生效使用

通过tsc --init命令生成 tsconfig.json 文件,tsconfig.json文件也叫做 typescript 编译配置文件

让 tsconfig.json 文件生效,使用 tsc demo.ts进行编译,编译后会得到demo.js文件,但是 tsconfig.json 文件并生效

打开tsconfig.json文件,找到complilerOptions属性下的removeComments:true选项,把注释去掉,这个配置项的意思是,编译时不显示注释,也就是编译出来的js文件不显示注释内容

这时候再运行编译代码tsc demo.ts,编译后打开demo.js文件,你会发现注释依然存在,说明tsconfig.json文件没有起作用

如果要想编译配置文件起作用,我们可以直接运行tsc命令,这时候tsconfig.json才起作用,可以看到生成的js文件已经不带注释了

多个 ts 文件选择性配置生效

默认文件体系下的多个 ts 文件都会同时被编译生效

使用 include 配置用来指定要编译的文件的,比如现在我们只编译demo.ts文件,而不编译demo2.ts文件,就可以这样写。

注意:配置文件不支持单引号,所以里边都要使用双引号;使用files的配置效果和include几乎一样

{"include":["demo.ts"],// "files":["demo.ts"],"compilerOptions": {//any something//........}
}

使用 exclude 配置用来说明除了指定的文件需要编译外其他文件不需要被编译,比如不编译 demo2 只编译 demo

{"exclude":["demo2.ts"],"compilerOptions": {//any something//........}
}

2、complierOptions 配置项详解

rootDir 和 outDir

现在你的js文件直接编译到了根目录下,和ts文件混在了一起。我们当然是不喜欢这种方法的,工作中我们希望打包的js都生成在特定的一个文件夹里,比如build。

这时候你就可以通过配置outDir来配置,当然你也可以通过rootDir来指定ts文件的位置,比如我们把所有的 ts 文件都放到 src 下。那配置文件就应该这样写。

{"outDir": "./build" ,"rootDir": "./src" ,
}

编译 ES6 语法到 ES5 语法 - allowJs

现在你在src目录下用ES6的语法写了一个demo2.js文件,代码如下。

export const name="蜡笔小新";

如果你不做任何配置,这时候使用tsc是没有效果的,我们需要到tsconfig.js文件里修改配置

"target":'es5' ,  // 这一项默认是开启的,你必须要保证它的开启,才能转换成功
"allowJs":true,   // 这个配置项的意思是联通

sourceMap 属性

如果把sourceMap的注释去掉,在打包的过程中就会给我们生成sourceMap文件.

sourceMap 简单说,Source map 就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置。有了它,出错的时候,编译工具将直接显示原始代码,而不是转换后的代码,这无疑给开发者带来了很大方便

noUnusedLocals 和 noUnusedParameters

比如现在我们修改demo.ts文件的代码,改为下面的样子。

const myname: string=null;
export const name="蜡笔小新";

这时候你会发现myname 这个变量没有任何地方使用,但是我们编译的话,它依然会被编译出来,这就是一种资源的浪费

这时候我们可以开启noUnusedLocals:true,开启后我们的程序会直接给我们提示不能这样编写代码,有没有使用的变量。

noUnusedParameters是针对于没有使用的函数的,方法和noUnusedLocals:true一样

学习TypeScript(TS),这一篇就足够了相关推荐

  1. 推荐 7 个学习 TypeScript 的宝库,2021 是时候给自己加薪了!

    大家好,新年快乐,我是你们的 猫哥,一个不喜欢吃鱼.又不喜欢喵 的超级猫 ~ 前言 猫哥是一个常年混迹在 GitHub 上的猫星人,所以发现了不少好的前端开源项目.常用技巧,在此分享给大家. 公众号: ...

  2. vue.js2.0 java_详解vite2.0配置学习(typescript版本)

    介绍 尤于溪的原话. vite与 Vue CLI 类似,vite 也是一个提供基本项目脚手架和开发服务器的构建工具. vite基于浏览器原生ES imports的开发服务器.跳过打包这个概念,服务端按 ...

  3. 深入浅出学习 TypeScript 语言

    课程简介 2012年10月,微软发布了首个公开版本的 TypeScript,2013年6月19日,在经历了一个预览版之后微软发布了正式版 TypeScript 0.9.TypeScript 是 Jav ...

  4. 学习动态性能表 第二篇--v$sesstat

    学习动态性能表 第二篇--v$sesstat  按照OracleOnlineBook中的描述,v$sesstat存储session从login到logout的详细资源使用统计. 类似于v$syssta ...

  5. 在WisOne平台上学习TypeScript

    TypeScript是微软公司推出的开源的类型化脚本语言,目的是用于为弱类型的javaScript提供强类型的识别和感知功能,同时它提供了类.接口.继承等相关在javaScript中不容易实现的功能, ...

  6. 学习Nginx,看这篇就就好了!(多图详解)

    李航 读完需要 10 分钟 速读仅需 3 分钟 " 本文主要帮助大家熟悉 Nginx 有哪些应用场景.Nginx 特点和架构模型以及相关流程.Nginx 定制化开发的几种模块分类.读完本文你 ...

  7. 菜鸟学习笔记:Java提升篇12(Java动态性2——动态编译、javassist字节码操作)

    菜鸟学习笔记:Java提升篇12(Java动态性2--动态编译.javassist字节码操作) Java的动态编译 通过脚本引擎执行代码 Java字节码操作 JAVAssist的简单使用 常用API ...

  8. 菜鸟学习笔记:Java提升篇8(线程2——线程的基本信息、线程安全、死锁、生产者消费者模式、任务调度)

    菜鸟学习笔记:Java提升篇8(线程2--线程的基本信息.线程安全.死锁.生产者消费者模式.任务调度) 线程的基本信息 线程同步 线程安全 死锁 生产者消费者模式 任务调度(了解) 线程的基本信息 J ...

  9. 菜鸟学习笔记:Java提升篇3(容器3——泛型、排序)

    菜鸟学习笔记:Java容器3--泛型.排序 泛型 泛型类 泛型接口 泛型方法 泛型继承 通配符"?" 泛型知识点补充 容器排序 Comparable接口与compareTo方法 C ...

最新文章

  1. python第三方库排行-scikit-learn: Python强大的第三方库
  2. 本地kubectl客户端连接远程K8S集群
  3. boost::hana::at_key用法的测试程序
  4. [ solr入门 ] - 利用solrJ进行检索
  5. springboot2.1.5集成finereport10.0过程中:手动安装本地jar包到maven仓库
  6. 【专升本计算机】专升本计算机期末考试复习题(A卷附答案)
  7. osg动态加载模型不显示_OSG仿真案例(8)——读取FBX格式文件并显示(无动画)...
  8. robot motion planning介绍
  9. 台式电脑蓝牙关了之后就开不了_台式电脑如何通过iPhone上网?
  10. MySQL高级-视图
  11. 解决datepicker设置选中日期setDate不生效问题
  12. Widows Live Writer
  13. 辨别虚假流量的十二种方法
  14. HDU 2955 Robberies抢劫案(01背包,变形)
  15. 使用Python PyQt5实现一个简单的图像识别软件
  16. vs2010开发activex(MFC)控件/ie插件(一)
  17. 有关Google面试的资料集合
  18. Flutter 不是真正的跨平台框架
  19. 2018湖南计算机对口高考C语言答案,2018年湖南省对口高考C语言试题
  20. python判断字符串间的包含关系

热门文章

  1. C语言常见的程序崩溃问题分析
  2. Python全栈之路系列之基础篇
  3. CF-Round#630 A-D
  4. 新媒体打工人教你如何零经验应聘文案岗
  5. [附源码]Nodejs计算机毕业设计流浪猫狗救助站Express(程序+LW)
  6. 企业CAX软件License资产管理的困局
  7. 伤心时最好读的50句语录
  8. C语言习题练习8--扫雷游戏
  9. 智能手表音频特性测试_儿童手表电磁辐射测试这一环节不可少
  10. 2017.2.14 日课