语法篇

一、基本类型

数据类型 关键字/描述 用法
数字类型 number let decLiteral: number = 6
布尔类型 boolean let flag: boolean = true;
字符串类型 string let name: string = “Runoob”
数组类型 array // 在元素类型后面加上[]
let arr: number[] = [1, 2];
// 使用数组泛型
let arr: Array = [1, 2];
元组 固定元素数量和类型,类型可不一致,
但位置必须一样
let x: [string, number];
x = [‘Runoob’, 1]; // 运行正常
x = [1, ‘Runoob’]; // 报错
console.log(x[0]); // 输出 Runoob
枚举 enum/定义数值集合 enum Color {Red, Green, Blue};
let c: Color = Color.Blue;
console.log©; // 输出 2
void void/表示该方法没有返回值 function hello(): void {
//没有return 返回值
}
null null/对象值缺失 let n: null = null;
undefined undefined/未定义的值 let u: undefined = undefined;
never never/never 是其它类型(包括 null 和
undefined)的子类型,代表从不会出现的值
// 返回never的函数必须存在无法达到的终点
function error(message: string): never { throw new Error(message); }
unknown unknown/unknown类型只能赋值给any类型和unknown类型 let value: unknown;
let value1: unknown = value; // OK
let value2: any = value; // OK
let value3: boolean = value; // Error

补充

enum类型

映射对应数据

1. 数字枚举:初始值可自动增长
实际场景:文章分类有固定的id 这时候就可以使用到枚举去定义

enum Category {Work,//这里是有默认初始值 为 0 依次增长 Life,Study,
}let cateGoryId: Category =Category.Studyconsole.log(cateGoryId)// 2

2.字符串枚举
定义的成员必须都是字符串
比如每个人会取自己的英文名,对应的英文名和真实人名,可以去做一一映射

enum Person {jack = '小王',role = '小蓝',Anna = '小红',
}let person: Person =Person.Annaconsole.log(person)//小红

3.异构枚举
异:就是里面成员既有数字又有字符串,大杂炖

enum mess {jack = '小王',role = '小蓝',Anna = '小红',c = 1,b = 2
}

二、断言

类型断言必须联合类型中的一种,类型断言只是做类型选择,而不是做类型转换
编译阶段起作用
在定义一个变量为联合类型时,要去做判断会遇到以下的情况

const unionGetLength2 = (something: string | number): number => {if(something.length){ //报错something无法去判断到底时哪个类型return something.length;} else {return something.toString().length;}
}

可以用断言去处理上面这个类型不能判断的问题,断言有两种写法:

  1. as语法
  2. 尖括号语法

1. as语法(值 as 类型)

const assertionGetLength = (something: string | number): number => {if((something as string).length){//告诉TS something 就是字符串类型return (something as string).length;} else {return something.toString().length;}
}

2. 尖括号语法(<类型>值)

const assertionGetLengthOther = (something: string | number): number => {if((<string>something).length){ 告诉ts something就是字符串类型return (<string>something).length;} else {return something.toString().length;}
}

三、类型守卫

1. 类型守卫

1.1 什么是类型守卫

当遇到条件语句时,会 ** 限制变量类型

  • 类型判断: typeof
  • 实例判断: instanceof
  • 属性判断: in
  • 字面量相等判断:=====!=!==

1.2 类型判断(typeof)

function test(own: string | boolean | number) {if (typeof own == 'string') {// 这里 own 的类型限制为 string} else if (typeof own == 'number') {// 这里 own 的类型限制为 number} else {// 这里 own 的类型限制为 boolean}
}

1.3 属性判断(in)

interface one {name: string;speak:string;
}interface two {age: number;see:string;
}function test(own:one | two){console.log("Name: " + own.name);if ("name" in own) { //这里限制为own 对象为oneconsole.log(own.speak);}if ("see" in own) {//这里限制为own限制的对象为twoconsole.log(own.see);}
}

1.4 实例判断(instanceof)

interface  Padder {getPaddingString():string
}
class Space implements Padder {constructor(private numSpaces: number) {} getPaddingString() {return Array(this.numSpaces + 1).join(' ');}
}
class StringPadder implements Padder {constructor(private value: string) {}getPaddingString() {return this.value;}
}function getrandom() {return Math.random() < 0.5 ? new Space(4) : new StringPadder('');
}let padder: Padder = getrandom();//判断padder是否是Space的实例对象,如果中间有其他值覆盖了,会出现问题
if (padder instanceof Space) {//判断后,确保这个值是它的实例对象 padder类型收缩在'SpaceRepeatingPadder'
}

2. 自定义类型守卫

返回布尔值条件函数

function isString (own: any): own is string {return typeof own === 'string';
}
function test (xdom:any) {if (isString(xdom)) {//xdom 限制为 'string'} else {//其他类型}
}

四、联合类型和类型别名

1. 联合类型

取值可以为多种类型中的一种
特点:1.使用的属性和方法需要类型共有的
2.通常与 nullundefined 一起使用:

let stringAndNumber: string | number;

2. 类型别名

类型另一个外号,用type定义

不用类型别名:
let greet = (message: string | string[]) => {// ...
};
用类型别名:
type Message = string | string[];
let greet = (message: Message) => {// ...
};

五、交叉类型

同时满足多个类型,多种类型叠加成为一种类型,要包含所需所有类型的特性

interface IPerson {id: string;age: number;
}interface IWorker {companyId: string;
}type IStaff = IPerson & IWorker;//定义IStaff类型 同时满足这两个接口类型条件const staff: IStaff = { //staff我i IStaff类型 必须一起满足才可id: 'E1006',age: 33,companyId: 'EFT'
};console.dir(staff)

六、函数

TypeScript JavaScript
含类型 无类型
箭头函数 箭头函数(ES2015)
函数类型 无函数类型
必填和可选参数 所有参数都是可选的
默认参数 默认参数
剩余参数 剩余参数
函数重载 函数重载

1. 普通函数

可以定义函数的参数类型和返回值

function createUserId(name:string,id:number) {return name + id
}

2. 箭头函数

let createUserId:(name:string,id:number)=>string

3. 可选参数

?表示这个参数是可选的
注意:可选参数要放在普通参数后面,不然会导致编译错误

function createUserId(name:string,id:number,age?:number) {return name + id;
}

4. 默认参数

默认name这个参数的值为Jons

function createUserId(name:string = 'Jons',id:number) {return name + id;
}

5. 剩余参数

简写,可以把剩余后面写的那些参数一起表示

function push(array,...items) {console.log(items)
}
push(a,1,2,3) //items是个数组 [1,2,3]

6. 函数重载

常见的根据参数的类型执行不同的函数
多数用于传入不同的参数得到不同的结果
重载分两个部分:1.声明 2.实现 缺一不可

6.1 重载使用场景

例1:
例如我们有一个add函数,可以接收string 类型相拼接,也可以接收number类型,相加

//声明:
function add (arg1: string, arg2: string): string
function add (arg1: number, arg2: number): number
//实现,
function add (arg1: string | number, arg2: string | number) {// 在实现上我们要注意严格判断两个参数的类型是否相等,而不能简单的写一个 arg1 + arg2if (typeof arg1 === 'string' && typeof arg2 === 'string') {return arg1 + arg2} else if (typeof arg1 === 'number' && typeof arg2 === 'number') {return arg1 + arg2}
}

注意:如果实现部分没有严格判断,会提示此重载签名与其实现签名不兼容。函数重载只是多个函数声明,逻辑依旧要自己写,并不会把我们声明的多个函数进行合并

例子2 :
写个函数test,当传入参数 param 是User时,不传入flag,当传入的param时number时,传入flag
下面看看不用重载:

interface User {name: string;age: number;
}declare function test(param: User | number, flag?: boolean): number;
const user={name:'Jack',
age:18
}
const res=test(user,false) //虽然不报错,但是与想法违背 当传入的是User是 此时应该不让传入flag

重载解决上诉问题:

interface User{name:string;age:number;
}
declare function  test(params:User):number;
declare function  test(params:number,flag:boolean):number;
const user={name:'jack',age:666
};
//类型“{ name: string; age: number; }”的参数不能赋给类型“number”的参数。ts(2345)
const res=test(user,false);

实际项目中的用法:
有声明之后,需要有具体的实现

interface User{name:string;age: number;
}
const user:User ={name:'jack',age:  123
}
class oneClass {//声明public test(param: User): number;public test(param: number, flag: boolean): number;//实现public test(param: User | number, flag?:boolean) {if (typeof param==='number') {return param+(flag?1:0)}else{return param.age}}
}

如果传入的参数不同,但是得到的结果是一样的,那么重载就意义不大了
重载个人觉得比较繁琐,一些可以用其他方法代替重载,反而更加的简单
例如:
可选参数来代替

function func (a: number): number
function func (a: number, b: number): number
//代替上面:
function func (a: number, b?: number): number

联合类型来代替:

function func (a: number): number
function func (a: string): number
//替代上面
function func (a: number | string): number

七、数组

ts在这个过程是类型校验,如果定义该类型,与后面数组对应数据冲突,会提示

//不能将类型 “ number ” 分配给类型 “ string ”
let x: number;
let y: number;
let z: string;
let five_array = [0, 1, 2, 3, 4];
[x, y, z] = five_array;

1. 基本类型的数组

定义一个只包含数字的数组:

const arr: number[] = [1,2,3]

既存数字又存字符串:

const arr1: (number | string)[] = [1, '2' ,3]

2. 对象类型数组

const objectArr: {name: string, age: number}[] = [{name:'a', age:16}]

3. 与元组对比

元组本质上也是数组,所以数组上的操作元组也可以去使用 一个数组里面的长度和类型都是固定的时候,就可以使用元祖

const teacherinfo2: [string, string, number] = ['zina', 'girl', 18];
//这里是固定长度以及固定了每一个的类型,如果类型不一样会提示

八、接口

接口来定义对象的类型

1. 写法

1.首字母大写
2.变量的形状必须和接口的形状保持一致
举个栗子:

interface Person {name:stringage:number
}
let jack:Person = { //变量的类型必须和上面是保持一致的name:'jack',age:18
}

2. 可选属性

和数组一样,对象里面的属性是可选的,我们经常需要不一样形状的对象

interface Person {name:stringage?:number
}let jack:Person = { name:'jack' // age 可以不写
}

3. 任意属性

用于不确定属性的数量的场景
确定属性和可选属性都必须符合任意属性的类型
如果不符合如下:

interface Person {name: string;age?: number;[propName: string]: string;
}
//类型“number”的属性“age”不能赋给字符串索引类型“string”。

正确写法:

interface Person {name:string;
age?:number;
[proppName:string]:any;
}

4. 只读属性

有些字段只能在创建的时候被赋值,其他时候不允许被更改,可以使用只读属性

interface Person {readonly id: number;name: string;age?: number;[propName: string]: any;
}let tom: Person = {name: 'Tom',gender: 'male'
};tom.id = 89757;
//无法分配到 "id" ,因为它是只读属性

九、泛型

类型不明确,但是要求其中一部分或者全部类型是一致的情况

使用场景

在不知道变量类型的情况下定义: 如果要求first输入的类型,second必须一样 这时候下面这个代码就不能做到了
可以用泛型解决这个的问题

function test(first:any,second:any){return `${first}+${second}`
}

泛型解决:T为自定义的,取ABC都可以

function test<T>(first:<T>,second:<T>){return `${first}+${second}`
}
test<number>(1,1)
test<number>(1,'1')//报错

可以定义一个数组里面的类型

function map<T>(params:T[]){return params
}
另一个写法
function map<T>(params:Array<T>){return params
}map<string>([1,'1'])//报错
map<string>(['1','1'])

定义多个泛型:

function test<T,P>(first:T,second:P):T{return first  //要求返回值和first 的类型一致
}
test<string,number>('1',1)
test('1',1) //不定义类型也可以,ts会自动推断出该T是string类型和P是number类型

十、类

1. 如何定义一个类

class Person {name = 'dell'getName(){return this.name;}
}
const person = new Person();
console.log(person.getName())//dell

2. 类的继承

class Person {name = 'dell'getName(){return this.name;}
}
class Teacher extends Person {getTeacherName(){return 'teacher'}
}
const teacher = new Teacher(); //声明的teacher实例里面 既有getName方法 又有getTeacherName
console.log(teacher.getName()); //dell
console.log(teacher.getTeacherName()) //teacher

3. 类的重写和super

在继承了父类方法之后,可以子类方法里面去重写父类的方法
注意:覆盖了之后,还需调用父类的方法,可以用 super 去调用

class Person {name = 'dell'getName(){return this.name;}
}
class Teacher extends Person {getTeacherName() {return 'teacher';}getName() {return 'lee';}
}
console.log(teacher.getName());//lee 这个时候子类的getName把父类的getName给覆盖了
// 如果Teacher 写成如下
class Teacher extends Person {getTeacherName() {return 'teacher';}getName() {// super.getName()//调用的是父类的方法return 'lee' + super.getName();}
}

4. 访问类型

4.1 private 私有的

允许在类内被使用
首先明确什么是类内,什么是类外

class Person {private name = 'dell'getName(){console.log(this.name)//类内 可以被调用}
}
const person = new Person()
console.log(person.name) //这个是类外 报错

4.2 protected 被保护的

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

class Person {protected name = 'dell'getName(){console.log(this.name)//类内 可以被调用}
}
class Teacher extends Person {getTeacherName() {console.log(this.name)//继承了父类的name 允许被调用}
}

4.3 public 公共的

允许我在类内外被调用,不写的情况默认就是public

class Person {name = 'dell'//默认前面都是public namegetName(){ //默认前面都是public getNameconsole.log(this.name)}
}
const person = new Person()
console.log(person.name)

5. constructor 构造函数

new 实例的时候 这个瞬间 constructor()被会马上执行

传统写法:
class Person {public name:stringconstructor(name:string){this.name=name}
}
const person =new  Person('dell')
console.log(person.name)
可以简化为:
class Person {constructor(public name: string) {}
}

继承中父子构造器冲突的情况:
继承之后 如果父类有构造器 子类也有构造器的时候 子类必须调用父类的构造函数。还必须按照父类的构造器的要求把参数传入

class Person{constructor(public name:string){}
}
class Teacher extends Person{constructor(public age:number){super('dell')}
}
const teacher =new Teacher(28)
console.log(teacher.age)//28
console.log(teacher.name)//dell

6. getter和setter

举个栗子:
假设某类有一个私有变量,但是又需要向外界去暴露这个私有变量,然后不能被外界知道这个变量的具体情况
可以用下面方法实现:
这里的getter和setter 可以对变量进行处理加工之后,向外界暴露,外界直接调用get/set的方法去读取更改_name这个属性

class Person{constructor(private _name:string){get name(){return this._name+' lee'; //可以将name加密之后暴露出去}set name(name:string){ //也可以保护变量const realName=name.split('')[0]; //对得到的name 进行一个处理this._name=realName}
}
const person=new Person('dell')
console.log(person.name);//dell lee 不需要括号
person.name ='dell lee'

7. 例子(单例模式)

永远只生成一个实例,当发现 instance 已经创建了之后,就不再创建实例了

class Demo{private static instance:Demo private constructor(public name:string){}// 不允许被调用 规避创建实例的情况static getInstance(){if(!this.instance){ //如果没有创建  创建让instance储存this.instance = new Demo('dell lee')}return this.instance;}}
const demo1 =Demo.getInstance();

8. 抽象类

主要是把有共性的部分去做一个封装
抽象类只能被继承 不能被 new

抽象类的用法 extends 子类如果继承了父类的抽象类之后,必须在子类里面去实现父类的抽象方法
举个栗子:算长方形,圆形 椭圆的面积 直接写 class 那么每个 class 下面都需要写这个方法,这个方法可以被提取出来写在抽象类里,再长方形,圆形,椭圆都去继承这个抽象类,各个形状的面积计算公式是不一样的,具体实现在自己的类里面去写

具体写法:

abstract class Geom{ //abstract 去定义一个抽象类getType(){return 'gemo';}abstract getArea():number //抽象方法 没有具体实现
}
class Circle extends Geom{private r:number
getArea(){return '123'
}}
class Square extends Geom{getArea(){return 'hello'
}
}
class Triangle extends Geom{getArea(){return ''
}
}

十一、装饰器

1. 什么是装饰器

修饰的工具
装饰器本身是一个函数

2. 装饰器种类

  • 类的装饰器
  • 方法的装饰器
  • 访问器的装饰器
  • 属性的装饰器
  • 参数的装饰器

3. 类的装饰器

3.1 如何写一个装饰器

通过@符号来使用,不能直接使用装饰器,在标准里面属于实验性质的语法,需要在 tsconfig.json 文件中把配置项打开


function testDecorator(constructor:any){constructor.prototype.getName = () =>{console.log('dell')}console.log('decorator')
}
@testDecorator
class Test{}//运行时机 会在类创建好之后,立马执行const test = new Test();

3.2 多个装饰器的执行顺序

收集的时候是从上到下依次收集
但是执行的时候会从下到上

function testDecorator1(constructor:any){console.log('decorator1')
}
function testDecorator2(constructor:any){console.log('decorator2')
}
@testDecorator1
@testDecorator2
class Test{}
//控制台:
//decorator2
//decorator1

3.3 装饰器包装

有时候装饰器里面会存在一些判断,可以用工厂模式去包装装饰器,里面返回一个函数

function testDecorator(flag:boolean){ //接收装饰器的参数if (flag) {return function (constructor: any) {constructor.prototype.getName = () => {console.log('dell');};console.log('decorator');};}else{return function (constructor: any) {}}}
@testDecorator(false)//装饰器返回的是一个函数,然后再调用该函数
class Test{}

4. 方法装饰器

方法装饰器接收三个参数

  • targe:普通方法, target 对象的是类的 prototype ,如果是静态方法 target对应的是类的构造函数
  • key:普通方法 key 装饰的方法的名字
  • descriptor: 属性描述符
function getNameDecorator(target:any,key:string,descriptor:PropertyDecorator){console.log(target, key, descriptor);
};

在创建完实例之后,对方法进行修改,如何让方法不被修改呢?如何让方法的原始值进行修改?
可以用 descriptor去控制

function getNameDecorator(target:any,key:string,descriptor:PropertyDescriptor){console.log(target, key, descriptor);descriptor.writable=false //方法不允许被修改descriptor.value = function() { //让方法里面返回的原始值进行修改return 'yeyeyeye'}
};
class Test{name:string;constructor(name:string){this.name=name;}@getNameDecoratorgetName(){ //class创建好之后,立刻对方法做一个装饰return this.name}
}
const test =new Test ('dell')
test.getName=()=>{ //errorreturn '123'
}

5. 访问器的装饰器

访问器的装饰器接收的参数和方法装饰器是一样的
访问器装饰器接收三个参数

  • targe:普通方法,target 对象的是类的prototype,如果是静态方法 target对应的是类的构造函数
  • key:普通方法 key 装饰的方法的名字
  • descriptor: 属性描述符

给set去写一个装饰器:

function visitDecorator(target: any,key: string,descriptor: PropertyDescriptor
) {console.log(target, key, descriptor);descriptor.writable = false; //方法不允许被修改
};
class Test{private  _name:string;constructor(name:string){this._name=name;}get name() {return this._name;}@visitDecoratorset name(name:string){this._name = name;}
}
const test =new Test ('dell')
test.name = '123123' //走的是 set 方法 会报错 set 上面的装饰器写了descriptor.writable = false 方法不允许被修改
console.log(test.name) //走的是 get 方法

6. 属性的装饰器

属性装饰器接收两个参数

  • targe:普通方法, target 对象的是类的 prototype,如果是静态方法 target 对应的是类的构造函数
  • key:被修饰的属性名

可以自己定义descriptor 返回 新的descriptor 可以去覆盖原始 name 的descriptor
比如下面:name 是可以进行修改的,自己定义descriptor 将 writable 更改成 false 之后 将不能被修改了

function nameDecorator(target: any,key: string,
):any{console.log(target, key);const descriptor :PropertyDescriptor ={writable:false}return descriptor;
};
class Test{name:string='dell';
}
const test =new Test ()
test.name = '123123'

7. 参数的装饰器

参数装饰器接收三个参数

  • targe:原型
  • method:方法名
  • paramIndex:参数所在的位置
function paramDecorator(target: any, method: string,paramIndex:number): any {console.log(target, method, paramIndex); //原型 getinfo 0
};
class Test{getinfo(@paramDecorator name:string,age:number){console.log(name,age)}
}
const test =new Test ()
test.getinfo('dell',30)

Vue.js+TS项目实践

1.项目环境搭建

npm i -g @vue/cli //安装 vue 脚手架
vue create vueAddts //创建 vue 项目
vue add @vue/typescript //创建 @vue/typescript
npm i vuex  //安装 vuex

2.Vuejs版与Vuejs+TS版区别

TS版: 需要先去导入两个组件 Component , Vue
Component组件注解,用来注册组件
vue-property-decorator 属性装饰器
如下:

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import ResList from '@/components/ResList.vue'@Component({components: {ResList}
})
export default class extends Vue {}

Vue版:对象的方式去描述整个vue

<script>
export default {name: "App",data(){return{}}
};
</script>

3.项目地址

项目跟着TS+Vue.js视频写的一个标签应用,对新手非常友好,强烈推荐小伙伴去看~
功能:对标签添加删除分类修改
感兴趣的可以点击这项目链接查看

4.了不起的 tsconfig.json 指南

写项目的时候没有太关注这边,所以贴大佬链接,想看的小伙伴转场啦~ 了不起的 tsconfig.json 指南

ts必备基础知识总结相关推荐

  1. python基础一入门必备知识-Python数据分析入门必备基础知识

    今天,老师要带大家解数据分析的定义.核心思路.应用领域以及开发流程,向大家全方位展示数据分析入门必备基础知识,全都是干货哦!虽然看完本文,不能让大家立马变身为一名数据分析师,但是能让大家对数据分析有一 ...

  2. 笔刷怎么做_零基础怎么学板绘?板绘小白必备基础知识

    零基础怎么学板绘?板绘小白必备基础知识!零基础学板绘需要准备什么东西?零基础学板绘需要学习哪些软件?板绘是做电影时要用到的人物场景原画的最重要的绘画方式,也是美术爱好者日常学习和创作的首选方式之一.那 ...

  3. java高手之路上的必备基础知识

    其实Java也就这么回事,重要的还是坚持,不能三天打鱼两天晒网.每一个分支下都是一门专业的技术,重要的是证明学精,熟练运用各项软件语言. 下面和大家分享java高手之路上的必备基础知识: 1.面向对象 ...

  4. 【网络通信】【电信运营商实战工程师】思科设备篇-网络工程师必备基础知识

    电信运营商实战工程师系列文章. 思科设备篇-网络工程师必备基础知识. 文章目录 1. 电信运营商网络设备机房 2. 认识并管理运营商网络设备 3. GNS3 安装与配置 4. IPv4地址及子网划分 ...

  5. 电商软件性能测试,实战 | 电商业务的性能测试(一): 必备基础知识

    原标题:实战 | 电商业务的性能测试(一): 必备基础知识 1. 测试步骤及模型分析 1.1 测试步骤总览 需求分析与测试设计(性能需求目标+业务模型拆解) 测试数据准备和构造(基于模型的数据准备) ...

  6. 电子工程师必备基础知识

    电子工程师必备基础知识(一) 运算放大器通过简单的外围元件,在模拟电路和数字电路中得到非常广泛的应用.运算放大器有好些个型号,在详细的性能参数上有几个差别,但原理和应用方法一样. 运算放大器通常有两个 ...

  7. 学习光盘刻录必备基础知识

    学习光盘刻录必备基础知识 2011年04月11日 [b] 学习光盘刻录必备基础知识[/b] 日期:2009-10-10 11:04 1.什么是CD-R? CD-R就是光盘刻录片(CD Recordab ...

  8. c语言需要哪些英语基础,学习C语言的必备基础知识(国外英语资料).doc

    学习C语言的必备基础知识(国外英语资料) 满卧裹瑟莉筑部获搪肪棱惺杀摄械圭旬敷豹休登悬邱雀报台盼拈毒鹰进怀却恩登雄旁二宇谊婆叔陌嘎扇体歌嫉蹿久题篡憨琵夹涌芦鸣褐颂诅讳拴狸果液梦绸亥氯确杯牌憨耗终贼况榔 ...

  9. LeetCode 牛客网 C++ 算法 刷题必备基础知识

    LeetCode 牛客网 C++ 算法 刷题必备基础知识 {ignore} 文章目录 LeetCode 牛客网 C++ 算法 刷题必备基础知识 {ignore} main综合模板 数组排序库 字符串库 ...

最新文章

  1. Linux 0.00 Makefile 说明
  2. php判断目录是否有写的权限,php中判断文件空目录是否有读写权限的函数代码_php技巧...
  3. leetcode——242. 有效的字母异位词
  4. 新国标电动自行车目录库
  5. Thinkphp 数据库配置参数
  6. 【英语学习】【Daily English】U08 Dating L04 We can Make it another time.
  7. OpenCV图像处理----图像的二值化
  8. 笔记:复旦IC卡专用芯片型号 -用于替代进口同类产品 - 草稿
  9. 在IIS上部署ASP网站
  10. 无背景图片添加白色背景
  11. 浙江大学计算机学院何钦铭,浙江大学导师介绍--何钦铭
  12. Zynq FPGA低时延H.264设计方案(编码+解码< 1ms)
  13. 单点登录SSO:图示和讲解
  14. 6-2 统计专业人数 (10分)
  15. cocos2d-x线程通信STL
  16. splint安装与配置
  17. 计算机毕业设计java+ssm的仓库进销存系统(源码+系统+mysql数据库+Lw文档)
  18. C++ 引用以及引用与指针的区别
  19. 【数字IC前端笔试真题精刷(2022年)】芯原——数字前端设计/验证
  20. HFSS-MATLAB-API

热门文章

  1. Unity Shader总结(十四)——卡通和素描风格的渲染
  2. wordexp函数学习
  3. linux照片备份软件,照片视频备份软件下载-照片视频备份云相册安卓版v1.0.1-Linux公社...
  4. 阀门定位器调节阀的特点及校验步骤
  5. 奔腾G7505怎么样 相当于什么水平
  6. mysql的考试视频_mysql期末考试选择题
  7. S2-MLP v2: Improved Spatial-Shift MLP Architecture for Vision
  8. mac android studio 模拟器启动不了,Mac os下android studio模拟器无法联网解决方法
  9. 酷乐天气开发记录总结4
  10. eve-ng和eNSP互联