2020 年最有前途的五种语言,TypeScript 已经成为其中之一。大约 60% 的前端程序员正在使用或曾使用过 TypeScript,而另外 22% 的开发者希望尝试使用。那么什么是 TypeScript?

TypeScript 和 JavaScript 语法没有明显的区别,意味着你无需学习很多知识就可以开始无缝编写 TypeScript 代码。简而言之,TypeScript 是 JavaScript 的超集。

所以你准备好了吗?如果没有,那么接下来这篇文章帮你。感兴趣的同学可以结合来自 Leslie/Jare 的官方系列教程 Cocos Creator 3.0 TypeScript 使用答疑一起食用~

本文由“壹伴编辑器”提供技术支

前言

相信经常关注前端技术的同学对 TypeScript 应该不陌生,或多或少看过一些关于 TypeScript 的文章。

各种技术论坛上也有不少关于 TypeScript 和 JavaScript 的讨论,大多数人对 TypeScript 都有着不错评价,但也有不少人觉得它没有存在的必要。

事实上,TypeScript 作为前端编程语言界的当红炸子鸡,配合代码编辑器界的当红炸子鸡 VS Code 能够让人拥有极佳的编码体验。

许多过去一直使用 JavaScript 的同学,在使用 TypeScript 之后,都觉得再也回不去了。

微软的这一套组合拳,打得多少人大喊真香!(真香定律虽迟但到 

它不是好不好用的问题,它真的是那种,那种很少见的那种......

鲁迅先生曾说过:人生苦短,我用 TS 。

—▼—

作为假前端的我,使用 TypeScript 进行开发也有一年半的时间了,也希望和各位分享一下我的看法。

所以在本篇文章我将以一名 Cocos Creator 开发者的角度,来对 TypeScript 做一波客观分析(强行安利),希望对各位有所帮助。

本文由“壹伴编辑器”提供技术支

大纲

1. 什么是 TypeScript

2. TypeScript 存在的意义

3. TypeScript 带来了什么改变

4. TypeScript 有什么特点

5. 如何创建 Creator TS 项目

6. 原有的 JS 项目如何使用 TS

本文由“壹伴编辑器”提供技术支

正文

什么是 TypeScript 

TypeScript 是一种微软开发并开源的跨平台编程语言,最初开发 TypeScript 的目的是为了更好地开发大型项目,其作者为大名鼎鼎的 C# 之父 Anders Hejlsberg 

在 TypeScript 中文主页中对于 TypeScript 的定义是“JavaScript 的超集”, TypeScript 支持JavaScript 的所有语法语义最新的 ECMAScript 特性,并且额外添加了很多特性

通过 TypeScript 编译器(tsc),TypeScript 代码可以被编译成纯净、简洁的 JavaScript 代码

主页中对 TypeScript 的介绍:

TypeScript 存在的意义

TypeScript 虽为大型项目而生,但是不代表它不适用于中小型项目,只是项目越大收益越明显。

TypeScript 弥补了 JavaScript 的许多不足,同时保留了 JavaScript 的灵活性,大大提高了项目的开发效率以及可维护性。

TypeScript 的诞生不是为了取代 JavaScript ,而是让 JavaScript 变得更好。

所以 TypeScript 对于开发者来说,不仅仅是一门编程语言,更是生产力工具。

—▼—

TypeScript 的良好口碑以及日渐庞大的生态,早就已经证明了它自己。

许多优秀的开源项目例如前端三大框架 AngularReact 和 Vue 均已支持 TypeScript ,Angular2 和 Vue 3.0 都是直接用 TypeScript 开发的

大多数第三方 JavaScript 库都提供了对 TypeScript 的支持

并且 Node.js 作者近期正式发布的 Deno 1.0 也是原生支持 TypeScript 

(可以看到 TypeScript 的未来一片光明...)

你几乎天天用来写代码的 VS Code 也是用 TypeScript 编写的。(用记事本写代码的大佬请先收起你的菜刀 

—▼—

而对于 Creator 开发者来说最最最重要的是:

Cocos Creator 引擎开发团队也建议开发者使用 TypeScript 进行开发。

目前 Creator 3D 只支持使用 TypeScript 进行开发。

我可以大胆的说未来 TypeScript 将会成为 Cocos Creator 开发的标配

TypeScript 带来了什么改变

既然 TypeScript 为大型项目而生,那不如就让我们看看 TypeScript 为什么适合大型项目?

在项目的开发中,必定少不了众多的开发人员,在这个模块化的时代,一个项目的多个模块可能均由不同的人来开发,并且每个人都有不同的编码习惯

在使用 JavaScript 进行开发时,由于没有类型限制、自动补全和智能提示,就需要开发人员之间的频繁沟通或者频繁阅读文档(详细的文档很关键)来保证代码可以正确执行。

即便如此,开发人员也不能保证每个变量/函数名都一次写对每个参数都一次传对

这些沟通和翻阅文档所花费的时间都在默默降低项目的整体开发效率。

而使用 TypeScript 进行开发时,得益于类型系统,在读取变量或调用函数时,均有自动补全基本杜绝写错变量/函数名的情况

类型限制智能提示让开发人员调用 API 时可以快速得知参数要求,不需要再频繁阅读代码、文档或询问模块开发者。

所有变量、函数和类都可以快速溯源(跳转到定义),让 TypeScript 代码有着较好的可维护性。合理利用注释甚至可以完全不看文档,真正做到“注释即文档”。(文档还是要有的 

总之就是开发效率 MAX !

TypeScript 的特点

  • 类型系统

众所周知 JS 是一门弱类型语言,不到执行时都不能确定变量的类型。编码时可以随心所欲反正不报错,一不小心就写出八哥( undefined 警告!)。

1. 静态类型检查让 TS 在编辑器中披上强类型语言的“马甲”,使得开发者在编码时就可以避免大多数类型错误的情况发生,而开发者要做的就只是声明变量时多写一个符号和一个单词。(当然你也可以在声明变量时不指定类型或者使用 any 类型来达到 JS 的动态类型效果,让 TypeScript 变成 AnyScript ,任性~ 

let name: string = '陈皮皮';
name = 9527; // 报错let age: any = 18;
age = 'eighteen'; // 不报错

真正做到早发现早解决早下班 

2. TS 在支持与 JS 几乎相同的原始类型之外,还额外提供了枚举(Enum)和元组(Tuple)的支持。(小声BB:再也不需要 cc.Enum 了)

// 枚举
enum Direction {Up = 1,Down,Left,Right
}
let direction: Direction = Direction.Up;// 元组
let x: [string, number];
x = ['hello', 10]; // 不报错
x = [10, 'hello']; // 报错

★ 另外类型系统配合声明文件(关于声明文件我们后面再聊)给我们带来了编辑器中完善的自动补全智能提示,大大增加了开发效率,也再不会因为拼错变量名或函数名而导致运行时的错误。(我知道 JS 加插件也能实现一定程度的智能提示但是语言自带它不香吗?)

—▼—

  • 修饰符和静态关键字

泪目,是从 C# 那里几乎原汁原味搬过来的一套修饰符和关键字,主要如以下几个:

1. 访问修饰符public private protected

用来限定类成员的可访问范围

个人觉得没有访问修饰符的封装是莫得灵魂的!

class Me {public name = '陈皮皮'; // 大家都知道我叫陈皮皮private secret = '*******'; // 我的秘密只有我知道protected password = '********'; // 我的支付宝密码会告诉我的后人的
}let me = new Me();
let a = me.name; // 拿到了我的名字
let b = me.secret; // 报错,私有的属性
let c = me.password; // 报错,受保护的属性class Child extends Me {constructor() {super();this.name = '陈XX';this.secret // 报错,无法访问this.password = '888888'; // 可以访问}
}

2. 静态关键字static

用于定义全局唯一的静态变量和静态函数

(在 Creator 的 JS 脚本中是用 cc.Class 的 static 属性来定义静态成员的,个人觉得使用体验极差)。

class Whatever {public static origin: string = 'Whatever';public static printOrigin() {console.log(this.origin);console.log(Whatever.origin);};
}console.log(Whatever.origin); // Whatever
Whatever.printOrigin(); // Whatever

3. 抽象关键字abstract

用来定义抽象类或抽象函数,面向对象编程很重要的一环(没对象的都面向屏幕编程吧,泪目)。

abstract class Animal {abstract eat(): void; // 不同动物进食的方式不一样
}let animal = new Animal(); // 报错,法实例化抽象类无class Dog implements Animal {eat() {console.log('我吃,汪!');}
}let dog = new Dog();
dog.eat(); // 我吃,汪!class Cat implements Animal {// 报错了,没有实现进食的功能
}

4. 只读关键字readonly

用来定义只读的字段,使得字段只能在创建的时候赋值一次。

class Human {name: string;readonly id: number;constructor(name: string, id: number) {this.name = name;this.id = id;}
}let human = new Human('陈皮皮', 666666);
human.name = '陈不皮'; // 名字可以改
human.id = 999999; // 报错,身份证号码一旦确定不能更改

—▼—

  • 接口

( C# 和 Java 的朋友们让我看到你们的双手好吗)

接口(interface)用于一系列成员的声明,但不包含实现,接口支持合并(重复声明),也可以继承于另一接口。下面给大家展示几个常见的用法:

1. 扩展原始类型

// 扩展 String 类型
interface String {/*** 翻译*/translate(): string;}// 实现翻译函数
String.prototype.translate = function () {return this; // 不具体写了,直接返回原字符串吧
};// 使用
let nickname = '陈皮皮'.translate();

2. 定义类型

interface Human {name: string; // 普通属性,必须有但是可以改readonly id: number; // 只读属性,一旦确定就不能更改hair?: number; // 可选属性,挺秃然的
}let ChenPiPi: Human = {name: '陈皮皮',id: 123456789,hair: 9999999999999
}

3. 类实现接口

interface Vehicle {wheel: number;engine?: string;run(): void;
}class Car implements Vehicle {wheel: 4;engine: '帝皇引擎';run() {console.log('小汽车跑得快!')}
}class Bike implements Vehicle {wheel: 2;run() {console.log('小黄车冲冲冲!')}
}

—▼—

  • 类型别名

这是一个比较常用的特性,作用如其名。

类型别名(type)用来给类型起一个新的名字

type 和接口(interface)很相似,type 可以作用于原始类型,联合类型,元组以及其它任何你需要手写的类型,interface 支持合并而 type 不可以。

type 同样也支持扩展,并且可以和接口互相扩展。

// 给原始类型起个小名
type UserName = string;
let userName: UserName = '陈皮';// 还可以是函数
type GetString = () => string;
let getString: GetString = () => {return 'i am string';
}
let result = getString();// 创建一个新的类型
type Name = {realname: string;nickname: string;
}
let name: Name = {realname: '吴彦祖',nickname: '陈皮皮'
}
// 再来一个新的类型
type Age = {age: number;
}
// 用上面两个类型扩展出新的类型
type User = Name & Age;
let user: User = {realname: '吴彦祖',nickname: '陈皮皮',age: 18,
}

—▼—

  • 联合类型

使用联合类型(Union Types)允许你在声明变量或接收参数时兼容多种类型

个人最喜欢的特性之一,点赞!

1. 表示一个值可以是几种类型之一

let bye: string | number;
bye = 886; // 不报错
bye = 'bye'; // 不报错
bye = false; // 报错

2. 让函数接受不同类型的参数,并在函数内部做不同处理

function padLeft(value: string, padding: string | number) {if (typeof padding === 'string') {return padding + value;} else {return Array(padding + 1).join('') + value;}
}padLeft('Hello world', 4); // 返回 '    Hello world'
padLeft('Hello', 'I said: '); // 返回 'I said: Hello'

—▼—

  • 泛型

( C# 和 Java 的朋友们再次让我看到你们的双手好吗)

使用泛型可以让一个/函数支持多种类型的数据,使用时可以传入需要的类型

又是一个非常实用的特性,利用泛型可以大大增加代码的可重用性,减少重复的工作,点赞!

以下是两个常用的用法:

1. 泛型函数

// 这是一个清洗物品的函数
function wash<T>(item: T): T {// 假装有清洗的逻辑...return item;
}class Dish { } // 这是盘子
let dish = new Dish(); // 来个盘子
// 盘子洗完还是盘子
// 用尖括号提前告诉它这是盘子
dish = wash<Dish>(dish);class Car { } // 这是汽车
let car = new Car(); // 买辆汽车
// 汽车洗完还是汽车
// 没告诉它这是汽车但是它认出来了
car = wash(car);

2. 泛型类

// 盒子
class Box<T>{item: T = null;put(value: T) {this.item = value;}get() {return this.item;}
}let stringBox = new Box<String>(); // 买一个用来装 String 的盒子
stringBox.put('你好!'); // 存一个 '你好!'
// stringBox.put(666); // 报错,只能存 String 类型的东西
let string = stringBox.get(); // 拿出来的是 String 类型

—▼—

  • 装饰器

这是一个相对比较高级的特性,以 @expression 的形式对类、函数、访问符、属性或参数进行额外的声明

利用装饰器可以做很多骚操作,感兴趣的话可以深入研究下。

1. 对类做预处理

export function color(color: string) {return function (target: Function) {target.prototype.color = color;}
}@color('white')
class Cloth {color: string;
}
let cloth = new Cloth();
console.log(cloth.color); // white@color('red')
class Car {color: string;
}
let car = new Car();
console.log(car.color); // red

2. Creator 中的 TS 组件中的 ccclass 和 property 就是两个装饰器

const { ccclass, property } = cc._decorator;@ccclass
export default class CPP extends cc.Component {@property(cc.Node)private abc: cc.Node = null;}

—▼—

  • 命名空间

命名空间(namespace)用来定义标识符的可用范围主要用于解决重名的问题,对于项目模块化有很大的帮助

Cocos Creator 中的 cc 就是一个内置的命名空间。

1. 对相同名字的类和函数进行区分

// pp 命名空间
namespace pp {export class Action {public static speak() {cc.log('我是皮皮!');}}
}// dd 命名空间
namespace dd {export class Action {public static speak() {cc.log('我是弟弟!');}}
}// 使用
pp.Action.speak(); // 我是皮皮!
dd.Action.speak(); // 我是弟弟!

2. 对接口进行分类

namespace Lobby {export interface Request {event: string,other: object// ...}
}namespace Game {export interface Request {event: string,status: string// ...}
}// 用于 Lobby 的请求函数
function requestLobby(request: Lobby.Request) {// ...
}// 用于 Game 的请求函数
function requestGame(request: Game.Request) {// ...
}

—▼—

  • 声明文件

声明文件(Declaration Files),即以 d.ts 作为后缀的代码文件,用来声明当前环境中可用的类型。

声明文件这一特性对于 TypeScript 来说是极其重要的,代码编辑器中的智能提示等特性都依赖于声明文件。

可以发现目前大多数第三方 JavaScript 库都有声明文件,声明文件让这些库在代码编辑器中也可以拥有类型检查智能提示等特性,使用体验 Max 。

我们甚至可以声明一些环境中不存在的类型,例如我在《微信小游戏接入好友排行榜》这篇文章中编写的 wx.d.ts 文件,使得我在编辑器环境中调用根本不存在的 wx 函数时不会报错且有智能提示。

一般 Cocos Creator 项目的根目录下都有一个声明文件 creator.d.ts ,文件中声明了 Cocos Creator 引擎几乎所有可用的 API 。所以即使是纯 JavaScript 的 Creator 项目,使用 cc 命名空间时也有智能提示。

Creator 中 TS 和 JS 在使用上的区别

  • 声明组件

在 TypeScript 脚本中 class 的声明方式 和 ES6 Class 相似,并使用了装饰器 @ccclass 来将普通 class 声明成 CCClass :

const { ccclass } = cc._decorator;@ccclass
export default class Test extends cc.Component {}

在 JavaScript 脚本中声明的方式:

cc.Class({extends: cc.Component,});

—▼—

  • 声明属性

在 TypeScript 脚本中需要使用装饰器 @property 来声明属性,基本类型可以不传参数(参数和使用 JavaScript 时基本一致):

const { ccclass, property } = cc._decorator;@ccclass
export default class Test extends cc.Component {@propertymyNumber: number = 666;@propertymyString: string = '666';@propertymyBoolean: boolean = true;@property(cc.Node)myNode: cc.Node = null;@property([cc.Node])myNodes: cc.Node[] = [];@property({visible: true,displayName: '位置',tooltip: '就是一个位置'})myVec2: cc.Vec2 = new cc.Vec2();@property({type: cc.Sprite,visible() { return this.myBoolean },tooltip: '当 myBoolean 为 true 才会展示该属性'})mySprite: cc.Sprite = null;@property_getset = 0;@propertyget getset() { return this._getset }set getset(value) { this._getset = value }}

在 JavaScript 脚本中需要在 properties 中定义属性(使用时没有智能提示,就很难受):

cc.Class({extends: cc.Component,properties: {myNumber: 666,myString: '666',myBoolean: true,myNode: cc.Node,myNodes: [cc.Node],myVec2: {default: new cc.Vec2(),visible: true,displayName: '位置',tooltip: '就是一个位置'},mySprite: {type: cc.Sprite,default: null,visible() { return this.myBoolean },tooltip: '当 myBoolean 为 true 才会展示该属性'},_getset: 0,getset: {get() { return this._getset; },set(value) { this._getset = value; }}}});

—▼—

  • 导入/导出组件/模块

在 TypeScript 脚本中使用 ES 模块的方式来导出或导入组件/模块:

// A.ts
const { ccclass, property } = cc._decorator;@ccclass
export default class A extends cc.Component {@propertypublic nickname: string = 'A';public greet() {cc.log('A: greet()');}}// B.ts
import A from "./A";const { ccclass, property } = cc._decorator;@ccclass
export default class B extends cc.Component {@property(A)private a: A = null;onLoad() {// 访问实例属性let nickname = this.a.nickname;// 调用实例函数this.a.greet();}}

在 JavaScript 脚本中使用的是 Common JS 模块的方式(其实 cc.Class 会默认导出,但是 VS Code 识别不了,所以一般都会用 module.export 导出。且使用时也没有智能提示全靠手打):

// A.js
let A = cc.Class({extends: cc.Component,properties: {nickname: 'A'},greet() {cc.log('A: greet()');}});module.export = A;// B.js
let A = require('./A');let B = cc.Class({extends: cc.Component,properties: {a: {type: A,default: null}},onLoad() {// 访问实例属性let nickname = this.a.nickname;// 调用实例函数this.a.greet();}});module.export = B;

—▼—

  • 静态变量/函数

在 TypeScript 脚本中直接使用 static 关键字声明静态变量和函数:

// A.ts
const { ccclass, property } = cc._decorator;@ccclass
export default class A extends cc.Component {public static id: number = 999999;public static staticGreet() {cc.log('A: staticGreet()');}}// B.ts
import A from "./A";const { ccclass, property } = cc._decorator;@ccclass
export default class B extends cc.Component {onLoad() {// 访问静态属性let id = A.id;// 调用静态函数A.staticGreet();}}

在 JavaScript 脚本中使用 static 属性来定义静态变量或函数(使用时没有智能提示全靠手打):

// A.js
let A = cc.Class({extends: cc.Component,static: {id: 999999,staticGreet() {cc.log('A: staticGreet()');}}});module.export = A;// B.js
let A = require('./A');let B = cc.Class({extends: cc.Component,onLoad() {// 访问静态变量let id = A.id;// 调用静态函数A.staticGreet();}});module.export = B;

—▼—

  • 枚举

上面也有说到 TS 自带枚举类型,所以在 TS 脚本中可以直接 enum 来定义枚举,而在 JS 脚本中需要用 cc.Enum 来定义枚举。

// TypeScript 脚本的方式
enum Direction {Up = 1,Down,Left,Right
}// JavaScript 脚本的方式
const Direction = cc.Enum({Up = 1,Down,Left,Right
});

如何创建 Creator TS 项目 

新建项目时,在项目模板中选择 Hello TypeScript ,就可以创建一个含有 TypeScript 相关配置和基本组件的项目。

原有的 JS 项目使用 TS

想要在原有的 JavaScript Creator 项目中使用 TypeScript ,需要点击编辑器上方主菜单的 [开发者 -> VS Code 工作流 -> 更新 VS Code 智能提示数据] 和 [开发者 -> VS Code 工作流 -> 添加 TypeScript 项目配置] 来给项目添加 creator.d.ts 声明文件和 tsconfig.json 配置文件。

  • creator.d.ts 是 Cocos Creator 引擎 API 的声明文件

  • tsconfig.json 是 TypeScript 项目的环境配置文件

在 Creator 项目中可以混用 JS 和 TS 脚本,也能享受到 TS 到来的福利。也就是说原有的 JS 脚本可以保留,不影响后续添加新的 TS 脚本。

但是如果想要将项目完全重构为 TS 项目,要做的就是将原有的 JS 脚本逐个修改为 TS 脚本,并对脚本内的写法进行转换。

对于较为复杂的项目,对项目代码进行重构这一行为可能需要花费较长的时间,如果没有做好充足的准备,不建议着手进行。

但是一旦完成重构,TS 绝不会让你失望,必定会给项目开发带来全方位的提升!

本文由“壹伴编辑器”提供技术支

学习资料

TypeScript 官网

https://www.typescriptlang.org

TypeScript 中文网

https://www.tslang.cn

TypeScript  开源代码仓库

https://github.com/Microsoft/TypeScript

Cocos Creator TypeScript 使用文档

https://docs.cocos.com/creator/manual/zh/scripting/typescript.html

TypeScript 入门教程 by xcatliu

https://github.com/xcatliu/typescript-tutorial

ECMAScript 6 入门 by 阮一峰

https://es6.ruanyifeng.com

awesome-typescript by semlinker

https://github.com/semlinker/awesome-typescript

本文由“壹伴编辑器”提供技术支

结束语

以上内容皆为陈皮皮的个人观点。

小生不才,文采不佳,如果写得不好还请各位多多包涵。如果有哪些地方说的不对,还请各位指出,希望与大家共同进步。

接下来我会持续分享自己所学的知识与见解,欢迎各位关注本公众号。

我们,下次见!

本文由“壹伴编辑器”提供技术支

往期精彩

为什么选择使用 TypeScript ?相关推荐

  1. 用typescript完成倒计时_「干货」将数十万行CoffeeScript代码迁移到TypeScript

    作者 | David Goldstein 译者 | 王强 策划 | 小智 转发链接:https://mp.weixin.qq.com/s/TK7kWXX4hR3e-jtpVMuBnw 序言 2017 ...

  2. Lyft的TypeScript实践

    来自Lyft的前端工程师Mohsen Azimi介绍了Lyft向TypeScript转型的过程,说明JavaScript类型系统的重要性.为什么Lyft选择TypeScript以及他们的一些实践经验. ...

  3. 推荐几个 VS Code 扩展、主题和字体

    前言 工欲善其事,必先利其器. VS Code 作为当前最流行的开源代码编辑器之一,要说它为什么这么受大众喜爱,我觉得一是它现代化的界面,二是它强大的扩展系统. 得益于 VS Code 的扩展系统,我 ...

  4. 这么全的 Cocos Creator 3.x 学习资源,竟然是免费的!

    目前 Cocos Creator 3.0 越来越成熟,使用 Cocos Creator 做游戏的小伙伴越来越多.我们在这里整理了现阶段最全面.最优质的 Cocos Creator 3.x 的学习资料, ...

  5. 为什么选择 TypeScript

    前言 相信经常关注前端技术的同学对 TypeScript 应该不陌生,或多或少看过一些关于 TypeScript 的文章. 各种技术论坛上也有不少关于 TypeScript 和 JavaScript ...

  6. 初步学习TypeScript

    使用Visual Studio Code搭建TypeScript开发环境 1.TypeScript是干什么的 ? TypeScript是由微软Anders Hejlsberg(安德斯·海尔斯伯格,也是 ...

  7. Typescript 精彩履历

    本章节和后续章节都以 Typescript 的口吻自述,就是这么自信(自恋). 兵法云:知己知彼,百战不殆(语出<孙子·谋攻篇>)(一个前端开始聊兵法,瞎搞,凑字数).引用此主要想说,要用 ...

  8. Visual Studio Code搭建TypeScript开发环境

    转载 http://www.cnblogs.com/sunjie9606/p/5945540.html 使用Visual Studio Code搭建TypeScript开发环境 1.TypeScrip ...

  9. typescript 怎么表示当前时间减一个月_TypeScript 入门知识点总结

    TypeScript 介绍 什么是 TypeScript 是 JavaScript 的一个超集,它可以编译成纯 JavaScript.编译出来的 JavaScript 可以运行在任何浏览器上,主要提供 ...

最新文章

  1. 如果宁静是 Oracle,万茜、张雨绮、黄圣依是什么?
  2. DirectX Shader 入门学习
  3. 物理磁盘空间使用已满导致数据库hang起
  4. 【Lucene4.8教程之一】使用Lucene4.8进行索引及搜索的基本操作
  5. E - Olympic Medal CodeForces - 215B(数学 思维)
  6. Android的面孔_Actiyity
  7. 全国python一级考试_全国青少年软件编程(python)等级考试试卷(一级)
  8. #436. 子串的最大差(单调栈)
  9. 基金侧袋机制: 指引与操作规范
  10. adb重启或关机手机命令
  11. 华中科技大计算机第八次基础作业,华中科技大计算机基础第三次作业.doc
  12. 解决idea导入项目中文乱码intellij
  13. 2017最新App Store 审核指南中文版
  14. google手机连接wifi后提示“无法连接互联网“的原因和解决方法
  15. 从程序员到项目经理(九):程序员加油站 — 再牛也要合群
  16. 两道2016年美国高中数学竞赛题
  17. 交易开拓者-附录二:函数速查
  18. mixamo骨骼_Mixamo——在线三维人物角色骨骼自动绑定,上千动作库直接生成人物动画...
  19. iOS(iPhone,iPad))开发(Obje…
  20. 关于国产化系统银河麒麟(Kylin)的问题记录--持续更新

热门文章

  1. Github精品:全开源的协同OA办公开发项目,不要错过!
  2. Hadoop集群SSH无密登录
  3. 变形监测基准点稳定性分析的必要性与方法?变形监测成果资料整理的内容和方法?3、变形分析与预测方法?
  4. Android studio 提示‘adb‘ 不是内部或外部命令,也不是可运行的程序的解决方法
  5. 最新新农村别墅自建房CAD设计施工图纸+2000套
  6. 《投资时报》报道云创大数据“稳经济”举措
  7. 抖音推广方法有哪些?抖音推广方式和技巧有哪些?
  8. 记录看到的crash相关的好网页
  9. 博文The Illustrated Transformer 的PDF格式
  10. python launcher卸载后蓝屏_卸载游戏后电脑蓝屏,想问怎么解决?