5分钟TypeScript入门
1.全局安装ts
npm install -g typescript
2.构建ts文件,编译成js
function greeter(person) { return "Hello, " + person;
}
let user = "Jane User";
document.body.innerHTML = greeter(user);
tsc greeter.ts
3.基本概念-类型注解
// TypeScript里的类型注解是一种轻量级的为函数或变量添加约束的方式。
// TypeScript提供了静态的代码分析,它可以分析代码结构和提供的类型注解。
// 如果类型错误,会编译报错,并指出报错的位置;
function greeter(person: string) { return "Hello, " + person;
}
let user = [0, 1, 2];
document.body.innerHTML = greeter(user);
4.基本概念-接口
interface Person { firstName: string; lastName: string;
}
function greeter(person: Person) { return "Hello, " + person.firstName + " " + person.lastName;
}
let user = { firstName: "Jane", lastName: "User" };
document.body.innerHTML = greeter(user);
5.基本概念-类
class Student { fullName: string; constructor(public firstName, public middleInitial, public lastName) { this.fullName = firstName + " " + middleInitial + " " + lastName; }
}
interface Person { firstName: string; lastName: string;
}
function greeter(person : Person) { return "Hello, " + person.firstName + " " + person.lastName;
}
let user = new Student("Jane", "M.", "User");
document.body.innerHTML = greeter(user);
6.手册指南-基础类型
布尔值
let isMarried: boolean = false;
数字
let age: number = 18;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
字符串
let name: string = "qinghuo";
let name: string = `qinghuo`;// 可以使用模板字符串
数组
let list: number[] = [1,2,3];
let list: string[] = ['a','b','c'];
let list: Array<number> = [1,2,3];
let list: Array<string> = ['a','b','c'];
元组
let list: [string,number];
list = ['a',1];//OK
list = [1,'a'];//error
// 当访问已知索引的元素的时候,会严格要求所属类型
console.log(list[0].substr(1)); // OK
console.log(list[1].substr(1)); // Error, 'number' does not have 'substr'
// 当访问越界元素的时候,会使用联合类型(string|number)任意其一
list[3] = 'world'; // OK, 字符串可以赋值给(string | number)类型
console.log(list[5].toString()); // OK, 'string' 和 'number' 都有 toString;
list[6] = true; // Error, 布尔不是(string | number)类型
枚举
// 枚举元素编号默认是从0开始的,但是可以手动修改
enum Color {red,green=3,blue}
let color: Color = Color.green;
let colorName: string = Color[4];
console.log(colorName);// 'blue',因为green编号被赋值为3,所以blue的编号就是4
Any
// any类型是十分有用,它允许你在编译时可选择地包含或移除类型检查。
let notSure: any = 4;
notSure = "qinghuo";//OK
Void
// 函数没有返回值时,常见void
function warnUser(): void { console.log("This is my warning message");
}
// 声明一个void类型的变量没有什么大用,因为你只能为它赋予undefined或null;
let unusable: void = undefined;
let unusable: void = null;
Null和Undefined
let u: undefined = undefined;
let n: null = null;
Never
// 返回never的函数必须存在无法达到的终点
function error(message: string): never { throw new Error(message);
}
// 推断的返回值类型为never
function fail() { return error("Something failed");
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never { while (true) { }
}
Object
declare function create(o: object | null): void;
create({ prop: 0 }); // OK
create(null); // OK create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error
类型断言
as
// 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用
let name: any = "qinghuo";
// 尖括号方式
let length: number = (<string>name).length;
// as方式
let length: number = (name as string).length;
7.手册指南-变量声明
let
块作用域
// 块作用域变量在包含它们的块或`for`循环之外是不能访问的
function f(input: boolean) { let a = 100; if (input) { // Still okay to reference 'a' let b = a + 1; return b; } // Error: 'b' doesn't exist here return b;
}
// 拥有块级作用域的变量的另一个特点是,它们不能在被声明之前读或写
a++; // illegal to use 'a' before it's declared;
let a;
重定义及屏蔽
let x = 10;
let x = 20; // 错误,不能在1个作用域里多次声明x
const
与
let
声明相似,但是就像它的名字所表达的,它们被赋值后不能再改变。 换句话说,它们拥有与let
相同的作用域规则,但是不能对它们重新赋值。
const numLivesForCat = 9;
const kitty = { name: "Aurora", numLives: numLivesForCat,
}
// Error
kitty = { name: "Danielle", numLives: numLivesForCat
};
// all "okay"
kitty.name = "Rory";
kitty.name = "Kitty";
kitty.name = "Cat";
kitty.numLives--;
解构数组
let input = [1, 2];
let [first, second] = input;
console.log(first); // 1
console.log(second); // 2// 使用扩展运算符...
let [first, ...rest] = [1, 2, 3, 4];
console.log(first); // 1
console.log(rest); // [ 2, 3, 4 ]
解构对象
let obj = {name: 'qinghuo',age: 18,height: 175
}
let {name,age} = obj;
console.log(name);//'qinghuo'
console.log(age);//18//使用扩展运算符...
let obj = {name: 'qinghuo',age: 18,height: 175
}
let {name,...other} = obj;
console.log(name);// 'qinghuo'
console.log(other);// {age:18,height:175}
属性重命名
let obj = {name: 'qinghuo',age: 18,height:175
};
let {name:a,age:b} = obj;
console.log(a);// 'qinghuo'
console.log(b);// 18
属性指定类型
let obj = {name: 'qinghuo',age: 18,height:175
};
let {name,age}:{name:string,age:number} = obj;
属性添加默认值
let obj = {name: 'qinghuo',age: 18,height:175
};
let {name,other=20} = obj;
console.log(name);//qinghuo
console.log(other);//20
函数声明
type C = { a: string, b?: number }
function f({ a, b }: C): void { // ...
}
扩展运算符
...
// 数组使用扩展运算符...
let a = [1,2];
let b = [3,4];
let c = [0,...a,...b,5];
console.log(c);// [0,1,2,3,4,5]//对象使用扩展运算符...
let a = {name:'qinghuo'};
let b = {age:18};
let c = {...a,...b};
console.log(c);// {name:'qinghuo',age:18}
8.手册指南-接口interface
必需属性
interface Jiekou {name: string;
}
// 要求这个对象参数有一个名为name的参数,并且是string属性
function infos(obj:Jiekou){console.log(obj.name);
}
infos({name:'qinghuo',age:18});
可选属性(属性后添加
?
)
可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误
interface SquareConfig { color?: string; width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } { let newSquare = {color: "white", area: 100}; if (config.clor) { // Error: Property 'clor' does not exist on type 'SquareConfig' newSquare.color = config.clor; } if (config.width) { newSquare.area = config.width * config.width; } return newSquare;
}
let mySquare = createSquare({color: "black"});
只读属性(属性前添加
readonly
)
interface People { readonly name: string; readonly age: number;
}
let a: People = { name: 'qinghuo', age: 18 };
a.age = 20; // error!
只读数组
ReadonlyArray<T>
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray<number> = a;
ro[0] = 12; // error!
ro.push(5); // error!
ro.length = 100; // error!
a = ro; // error!// 把整个ReadonlyArray赋值到一个普通数组也是不可以的,但是可以用类型断言重写:
a = ro as number[];
readonly
vsconst
最简单判断该用
readonly
还是const
的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用const
,若做为属性则使用readonly
。
额外的属性检查
interface SquareConfig { color?: string; width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } { //...
}
// error: 'colour' not expected in type 'SquareConfig'`
let mySquare = createSquare({ colour: "red", width: 100 });
// 可以使用类型断言,绕开这些检查
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
// 最佳方式是,添加一个字符串索引签名
interface SquareConfig { color?: string; width?: number; [propName: string]: any;
}
// 最后一种跳过这些检查的方式,就是将这个对象赋值给一个另一个变量: 因为`squareOptions`不会经过额外属性检查,所以编译器不会报错。
let squareOptions = { colour: "red", width: 100 };
let mySquare = createSquare(squareOptions);
函数类型
interface SearchFunc { (source: string, subString: string): boolean;
}let mySearch: SearchFunc;
mySearch = function(src: string, sub: string): boolean {let result = src.search(sub); return result > -1;
}
可索引的类型
定义了StringArr接口,它具有索引签名。
这个索引签名表示了当用number去索引StringArr时会得到string类型的返回值。
interface StringArr {[index: number]: string;
}let arr: StringArr;
arr = ["qinghuo", "五星大饭店"];let str: string = arr[0];
console.log(str);//'qinghuo'
TypeScript支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用
number
来索引时,JavaScript会将它转换成string
然后再去索引对象。 也就是说用100
(一个number
)去索引等同于使用"100"
(一个string
)去索引,因此两者需要保持一致。
class Animal {name: string;
}
class Dog extends Animal {breed: string;
}// 错误:使用数值型的字符串索引,有时会得到完全不同的Animal!
interface NotOkay {[x: number]: Animal;[x: string]: Dog;
}
name
的类型与字符串索引类型不匹配,所以类型检查器给出一个错误提示:
interface NumberDictionary {[index: string]: number;length: number; // 可以,length是number类型name: string // 错误,`name`的类型与索引类型返回值的类型不匹配
}
可以将索引签名设置为只读,这样就防止了给索引赋值:
interface ReadonlyStringArray {readonly [index: number]: string;
}
let arr: ReadonlyStringArray = ["qinghuo", "五星大饭店"];
arr[2] = "abc"; // error!
类类型
interface ClockInterface {currentTime: Date;setTime(d: Date);
}class Clock implements ClockInterface {currentTime: Date;setTime(d: Date) {this.currentTime = d;}constructor(h: number, m: number) { }
}
类静态部分与实例部分的区别
interface ClockConstructor {new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {tick();
}function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {return new ctor(hour, minute);
}class DigitalClock implements ClockInterface {constructor(h: number, m: number) { }tick() {console.log("beep beep");}
}
class AnalogClock implements ClockInterface {constructor(h: number, m: number) { }tick() {console.log("tick tock");}
}let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
继承接口
interface Shape {color: string;
}interface PenStroke {penWidth: number;
}interface Square extends Shape, PenStroke {sideLength: number;
}let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;
混合类型
interface Counter {(start: number): string;interval: number;reset(): void;
}function getCounter(): Counter {let counter = <Counter>function (start: number) { };counter.interval = 123;counter.reset = function () { };return counter;
}let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
接口继承类
class Control {private state: any;
}interface SelectableControl extends Control {select(): void;
}class Button extends Control implements SelectableControl {select() { }
}class TextBox extends Control {select() { }
}// 错误:“Image”类型缺少“state”属性。
class Image implements SelectableControl {select() { }
}class Location {}
在上面的例子里,
SelectableControl
包含了Control
的所有成员,包括私有成员state
。 因为state
是私有成员,所以只能够是Control
的子类们才能实现SelectableControl
接口。 因为只有Control
的子类才能够拥有一个声明于Control
的私有成员state
,这对私有成员的兼容性是必需的。
在Control
类内部,是允许通过SelectableControl
的实例来访问私有成员state
的。 实际上,SelectableControl
接口和拥有select
方法的Control
类是一样的。Button
和TextBox
类是SelectableControl
的子类(因为它们都继承自Control
并有select
方法),但Image
和Location
类并不是这样的。
9.手册指南-类
实例
声明一个
Greeter
类。这个类有3个成员:一个叫做greeting
的属性,一个构造函数和一个greet
方法。
class Greeter {greeting: string;constructor(message: string) {this.greeting = message;}greet() {return "Hello, " + this.greeting;}
}let greeter = new Greeter("world");
继承
extends
最基本的继承:类从基类中继承了属性和方法。 这里,
Dog
是一个派生类,它派生自Animal
基类,通过extends
关键字。 派生类通常被称作子类,基类通常被称作超类。
因为Dog
继承了Animal
的功能,因此我们可以创建一个Dog
的实例,它能够bark()
和move()
。
class Animal {move(distanceInMeters: number = 0) {console.log(`Animal moved ${distanceInMeters}m.`);}
}class Dog extends Animal {bark() {console.log('Woof! Woof!');}
}const dog = new Dog();
dog.bark(); // 'Woof! Woof!'
dog.move(10); // Animal moved 10m
dog.bark(); // 'Woof! Woof!'
复杂的实例
这一次,我们使用
extends
关键字创建了Animal
的两个子类:Horse
和Snake
。
与前一个例子的不同点是,派生类包含了一个构造函数,它必须调用super()
,它会执行基类的构造函数。 而且,在构造函数里访问this
的属性之前,我们一定要调用super()
。 这个是TypeScript强制执行的一条重要规则。
class Animal {name: string;constructor(theName: string) { this.name = theName; }move(distanceInMeters: number = 0) {console.log(`${this.name} moved ${distanceInMeters}m.`);}
}class Snake extends Animal {constructor(name: string) { super(name); }move(distanceInMeters = 5) {console.log("Slithering...");super.move(distanceInMeters);}
}class Horse extends Animal {constructor(name: string) { super(name); }move(distanceInMeters = 45) {console.log("Galloping...");super.move(distanceInMeters);}
}let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");sam.move(); // Sammy the Python move 5m;
tom.move(34);//Tommy the Palomino move 34m;
修饰符
public
在TypeScript里,成员都默认为
public
。
class Animal {public name: string;public constructor(theName: string) { this.name = theName; }public move(distanceInMeters: number) {console.log(`${this.name} moved ${distanceInMeters}m.`);}
}
修饰符
private
当成员被标记成
private
时,它就不能在声明它的类的外部访问。
class Animal {private name: string;constructor(theName: string) { this.name = theName; }
}new Animal("Cat").name; // 错误: 'name' 是私有的.
修饰符
protected
protected
修饰符与private
修饰符的行为很相似,但有一点不同,protected
成员在派生类中仍然可以访问
class Person {protected name: string;constructor(name: string) { this.name = name; }
}class Employee extends Person {private department: string;constructor(name: string, department: string) {super(name)this.department = department;}public getElevatorPitch() {return `Hello, my name is ${this.name} and I work in ${this.department}.`;}
}let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // 错误
注意,我们不能在
Person
类外使用name
,但是我们仍然可以通过Employee
类的实例方法访问,因为Employee
是由Person
派生而来的。
构造函数也可以被标记成protected
。 这意味着这个类不能在包含它的类外被实例化,但是能被继承。比如,
class Person {protected name: string;protected constructor(theName: string) { this.name = theName; }
}// Employee 能够继承 Person
class Employee extends Person {private department: string;constructor(name: string, department: string) {super(name);this.department = department;}public getElevatorPitch() {return `Hello, my name is ${this.name} and I work in ${this.department}.`;}
}let howard = new Employee("Howard", "Sales");
let john = new Person("John"); // 错误: 'Person' 的构造函数是被保护的.
修饰符
readonly
使用
readonly
关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化
class Octopus {readonly name: string;readonly numberOfLegs: number = 8;constructor (theName: string) {this.name = theName;}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.
存取器
TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
let passcode = "secret passcode";class Employee {private _fullName: string;get fullName(): string {return this._fullName;}set fullName(newName: string) {if (passcode && passcode == "secret passcode") {this._fullName = newName;}else {console.log("Error: Unauthorized update of employee!");}}
}let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {alert(employee.fullName);
}
我们可以修改一下密码,来验证一下存取器是否是工作的。当密码不对时,会提示我们没有权限去修改员工。
对于存取器有下面几点需要注意的:
首先,存取器要求你将编译器设置为输出ECMAScript 5或更高。 不支持降级到ECMAScript 3。 其次,只带有get
不带有set
的存取器自动被推断为readonly
。 这在从代码生成.d.ts
文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。
静态属性
们也可以创建类的静态成员,这些属性存在于类本身上面而不是类的实例上。 在这个例子里,我们使用
static
定义origin
,因为它是所有网格都会用到的属性。 每个实例想要访问这个属性的时候,都要在origin
前面加上类名。 如同在实例属性上使用this.
前缀来访问属性一样,这里我们使用Grid.
来访问静态属性。
class Grid {static origin = {x: 0, y: 0};calculateDistanceFromOrigin(point: {x: number; y: number;}) {let xDist = (point.x - Grid.origin.x);let yDist = (point.y - Grid.origin.y);return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;}constructor (public scale: number) { }
}let grid1 = new Grid(1.0); // 1x scale
let grid2 = new Grid(5.0); // 5x scaleconsole.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
抽象类
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。
abstract
关键字是用于定义抽象类和在抽象类内部定义抽象方法。
abstract class Animal {abstract makeSound(): void;move(): void {console.log('roaming the earch...');}
}
抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。 抽象方法的语法与接口方法相似。 两者都是定义方法签名但不包含方法体。 然而,抽象方法必须包含
abstract
关键字并且可以包含访问修饰符。
abstract class Department {constructor(public name: string) {}printName(): void {console.log('Department name: ' + this.name);}abstract printMeeting(): void; // 必须在派生类中实现
}class AccountingDepartment extends Department {constructor() {super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()}printMeeting(): void {console.log('The Accounting Department meets each Monday at 10am.');}generateReports(): void {console.log('Generating accounting reports...');}
}let department: Department; // 允许创建一个对抽象类型的引用
department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
department.generateReports(); // 错误: 方法在声明的抽象类中不存在
类和构造函数的关系
编译前如下:
class Greeter {greeting: string;constructor(message: string) {this.greeting = message;}greet() {return "Hello, " + this.greeting;}
}let greeter: Greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
编译后如下:
let Greeter = (function () {function Greeter(message) {this.greeting = message;}Greeter.prototype.greet = function () {return "Hello, " + this.greeting;};return Greeter;
})();let greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
上面的代码里,
let Greeter
将被赋值为构造函数。 当我们调用new
并执行了这个函数后,便会得到一个类的实例。 这个构造函数也包含了类的所有静态属性。 换个角度说,我们可以认为类具有_实例部分_与_静态部分_这两个部分。
让我们稍微改写一下这个例子,看看它们之间的区别:
class Greeter {static standardGreeting = "Hello, there";greeting: string;greet() {if (this.greeting) {return "Hello, " + this.greeting;}else {return Greeter.standardGreeting;}}
}let greeter1: Greeter;
greeter1 = new Greeter();
console.log(greeter1.greet());let greeterMaker: typeof Greeter = Greeter;
greeterMaker.standardGreeting = "Hey there!";let greeter2: Greeter = new greeterMaker();
console.log(greeter2.greet());
这个例子里,
greeter1
与之前看到的一样。 我们实例化Greeter
类,并使用这个对象。 与我们之前看到的一样。
再之后,我们直接使用类。 我们创建了一个叫做greeterMaker
的变量。 这个变量保存了这个类或者说保存了类构造函数。 然后我们使用typeof Greeter
,意思是取Greeter类的类型,而不是实例的类型。 或者更确切的说,“告诉我Greeter
标识符的类型”,也就是构造函数的类型。 这个类型包含了类的所有静态成员和构造函数。 之后,就和前面一样,我们在greeterMaker
上使用new
,创建Greeter
的实例。
把类当做接口使用
类定义会创建两个东西:类的实例类型和一个构造函数。 因为类可以创建出类型,所以你能够在允许使用接口的地方使用类。
class Point {x: number;y: number;
}interface Point3d extends Point {z: number;
}let point3d: Point3d = {x: 1, y: 2, z: 3};
10.手册指南-函数
11.手册指南-泛型
12.手册指南-枚举
13.手册指南-类型推论
14.手册指南-类型兼容性
15.手册指南-高级类型
16.手册指南-Symbols
17.手册指南-迭代器和生成器
18.手册指南-模块
19.手册指南-命名空间
20.手册指南-命名空间和模块
21.手册指南-模块解析
22.手册指南-声明合并
23.手册指南-JSX
基本介绍
- 给文件一个
.tsx
扩展名 - 启用
jsx
选项
TypeScript具有三种JSX模式:
preserve
,react
和react-native
。 这些模式只在代码生成阶段起作用 - 类型检查并不受影响。
模式 | 输入 | 输出 | 输出文件扩展名 |
---|---|---|---|
preserve | .jsx | ||
react | React.createElement(“div”) | .js | |
react-native | .js |
as操作符
var foo = <foo>bar;
//由于不能够在.tsx文件里使用上述语法,因此我们应该使用另一个类型断言操作符:as
var foo = bar as foo;
类型检查
为了理解JSX的类型检查,你必须首先理解固有元素与基于值的元素之间的区别。
- 对于React,固有元素会生成字符串(
React.createElement("div")
),然而由你自定义的组件却不会生成(React.createElement(MyComponent)
)。- 传入JSX元素里的属性类型的查找方式不同。 固有元素属性_本身_就支持,然而自定义的组件会自己去指定它们具有哪个属性。
24.手册指南-装饰器
25.手册指南-Mixins
26.手册指南-三斜线指令
27.手册指南-js文件类型检查
原文链接
5分钟TypeScript入门相关推荐
- python新手教程 从零开始-Python零基础从零开始学习Python十分钟快速入门
原标题:Python零基础从零开始学习Python十分钟快速入门 学习Python的,都知道Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.Python是一种动态解释型的 ...
- 我写的第一本书《TypeScript 入门教程》
阅读原文 持续了大半年的学习和写作,在今天终于告一段落了. 写书之旅 最初有写书的想法,是刚加入微软的时候. 由于工作中需要重度使用 TypeScript,所以我花了几天的时间研读了好几遍官方手册和中 ...
- 九十分钟极速入门Linux——Linux Guide for Developments 学习笔记
转载自: 九十分钟极速入门Linux--Linux Guide for Developments 学习笔记 http://mp.weixin.qq.com/s?__biz=MzAwNTMxMzg1MA ...
- PyTorch 深度学习: 60 分钟极速入门
PyTorch 深度学习: 60 分钟极速入门 2019年年初,ApacheCN组织志愿者翻译了PyTorch1.2版本中文文档(github地址),同时也获得了PyTorch官方授权,我相信已经有许 ...
- 2016windows(10) wamp 最简单30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world...
2016最简单windows(10) wamp 30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world thrift是什么 最简单解释 thrift是用来帮助各个编程语 ...
- 60 分钟极速入门 PyTorch
2017 年初,Facebook 在机器学习和科学计算工具 Torch 的基础上,针对 Python 语言发布了一个全新的机器学习工具包 PyTorch. 因其在灵活性.易用性.速度方面的优秀表现,经 ...
- python十分钟教程_简洁的十分钟Python入门教程
[简介] Python是一种动态解释型的编程语言.Python可以在Windows.UNIX.MAC等多种操作系统上使用,也可以在Java..NET开发平台上使用. [特点] 1 Python使用C语 ...
- 其实python面向对象3分钟就可以入门(14)
本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课程也将 ...
- thinkcmf搭建教程_5分钟快速入门
# 5分钟快速入门 [TOC=1,5] ## 1.创建模板目录 在`public/themes/`目录下创建`quick_start`目录 ## 2.添加模板描述文件 在`public/themes/ ...
- Mysql学习总结(12)——21分钟Mysql入门教程
21分钟 MySQL 入门教程 目录 一.MySQL的相关概念介绍 二.Windows下MySQL的配置 配置步骤 MySQL服务的启动.停止与卸载 三.MySQL脚本的基本组成 四.MySQL中的数 ...
最新文章
- 苹果6尺寸_小屏+刘海被安卓阵营抛弃,苹果却玩出了花
- RecyclerView上拉加载Demo
- css处理超出文本截断问题的两种情况(多行或者单行)
- linux虚拟文件系统vfs
- 常见的6种JavaScript设计模式
- 修改oracle用户资源限制,RHEL5中安装Oracle11gR2修改用户SHELL限制、环境配置、内核参数...
- 基于webpack3.x从0开始搭建React开发环境
- Python 爬虫利器二之 Beautiful Soup 的用法
- 信息如何实现病毒式传播?一文看懂Gossip协议
- 一个spark receiver 或多个spark receiver 接收 多个flume agent
- ERROR 1064 (42000): ; check the manual that corresponds to y
- python 网络编程 异步io_python网络编程——网络IO模型
- 手机上编写Java程序的软件
- 从零构建知识图谱(技术、方法与案例)-第一章:知识图谱概览
- ion-infinite-scroll上拉加载 ion-refresher下拉刷新
- 消防中计算机基础知识,消防基础知识考试题
- 网络复现之基于TPS的STN网络
- C语言--Union类型的使用方法
- 商业银行的科技发展趋势
- 【格灵深瞳】电话面试
热门文章
- SAP OOALV-SD模块实战开发案例(增删改查)
- 寒江独钓学习笔记 -- 第四章 Hook分发函数 过滤键盘输入
- 化工厂定位系统健全企业安全体系
- ewebeditor
- Java ini文件读写修改配置内容以及使用org.dtools.javaini-v1.1.00.jar中文乱码
- 计算机密码学论文,密码学论文写作范例论文
- java detach_jQuery中detach()方法用法实例
- PVE系统更换大硬盘的扩容方法
- 基于团队的持续优化之道
- 财务管理流程图怎么画之你需要了解的流程图绘制技巧