Tpyescript
typescitpt安装 编译
安装
npm install -g typescript
yarn global add typescipt
tsconfig.json配置文件
{
"compilerOptions": {
"module": "CommonJS",
"outDir": "./dist",
"target": "es5",
"strictNullChecks": true,
"watch": true
},
"include": [
"./src/**/*.ts"
],
"exclude": [
"node_modules"
]
}
执行命令
tsc
typescript中的数据类型
//布尔类型(boolean) true false
var flag:boolean=true;
//数字类型
var a:number=123;
console.log(a)
//字符串类型
var str:string="this is demo";
// str=111; 报错
// 数组类型(array) ts中定义数组有两种方式
//1.第一种定义数组方式
// let arr:number[]=[1,2,3,4,\'122\']; 报错,数组元素必须全是数字
let arr:string[]=[\'php\',\'.net\',\'go\']; //字符串数组
//2.第二种定义数组的方式
let arr1:Array<number>=[1,2,3,4,5];
console.log(arr1);
//元祖类型 tuple 属于数组的一种
let arr2:[string,number,boolean]=[\'ts\',3.12,true];
//枚举类型,事先考虑到某一变量可能取得值,尽量用自然语言中含义清楚的单词来表示它的每一个值,这种方法称为枚举方法。用这种方法定义的类型称为枚举类型
/*
* enum 枚举名{
* 标识符[=整型常数],
* 标识符[=整型常数],
* ....
* 标识符[=整型常数],
* };
* //举例; pay_status 0 未支付 1支付 2 交易成功
* */
enum Flag{
success=1,
error=-1
}
var f:Flag=Flag.success;
console.log(f);//1
//任意类型 (any) 可以是任意类型。
var num:any="122";
num="str";
//任意类型的用法 可以用来解决获取dom节点的时候ts报错。
// var oBox:any=document.getElementById(\'box\');
// oBox.style.color=\'red\';
//null和undefined 其他数据类型的子类型
//定义没有赋值就是undefined
var num1:number | undefined;
console.log(num1);
var num2:null;
num2=null;
//元素可能是number类型,也可能是null,可能是undefined
var num3:number | null | undefined;
num3=1222;
console.log(num3)
//void类型 typescript 中的void表示没有任何类型 一般用于定义方法的时候方法没有返回值
function run():void {
console.log(\'run\');
}
run();
//never类型,是其他类型(包括null和undefined)的子类型,代表从不会出现的值。这意为着never的变量只有被never类型所赋值。
typescript中的函数
/*
* ts中的函数用法
* */
//函数中声明法
function run1():string{
return \'1222\'
}
//匿名函数
var fun2=function():number{
return 11;
}
console.log(fun2()); //调用方法
//ts中定义传参
function getInfo(name:string,age:number):string{
return `${name}---${age}`
}
console.log(getInfo(\'zhangsan\',20));
//没有返回值的方法
function run2():void{
console.log(\'1111\');
}
run2();
//方法可选参数 要使用? 注意可选参数必须配置到参数的最后面
function getInfo1(name:string,age?:number):string{
if(age){
return `${name}---${age}`
}else{
return `${name}---年龄保密`
}
}
console.log(getInfo1(\'张三\'));
console.log(getInfo1(\'张三\',122));
//默认参数
function getInfo2(name:string,age:number=20):string{
if(age){
return `${name}---${age}`
}else{
return `${name}---年龄保密`
}
}
console.log(getInfo2(\'张三\'));
console.log(getInfo2(\'张三\',122));
//剩余参数
//三点运算符 接收新参数传过来的值
function sum(...result:number[]):number{
let sum=0;
for(var i=0;i<result.length;i++){
sum+=result[i]
}
return sum;
}
console.log(sum(1,3,7)); //11
//第二种写法
function sum1(a:number,b:number,...result:number[]):number{
let sum=a+b;
for(var i=0;i<result.length;i++){
sum+=result[i]
}
return sum;
}
console.log(sum1(1,3,7,333)); //344
//函数重载
/* 重载指的是两个或者两个以上同名函数,但他们的参数不一样,这时会出现函数重载的情况*/
/* typescript中的重载,通过为统一函数提供多个函数类型定义来尝试下多种功能的目的*/
function getInfo3(name:string):string;
function getInfo3(age:number):string;
function getInfo3(str:any):any{
if(typeof str===\'string\'){
//字符串类型
return \'我叫:\'+str
}else{
//数字类型
return \'我的年龄是:\'+str
}
}
console.log(getInfo3(\'张三\')); //正确
console.log(getInfo3(1222)); //正确
// console.log(getInfo3(true)); 报错
function getInfo4(name:string):string;
function getInfo4(name:string,age:number):string;
function getInfo4(name:any,age?:any):any{
if(age){
return \'我叫:\'+name+\'年龄是\'+age
}else{
return \'我叫:\'+name
}
}
console.log(getInfo4(\'张三\')); //正确 我叫:张三
console.log(getInfo4(\'猪头\',111)); //正确 我叫:猪头年龄是111
//箭头函数 es6 箭头函数里面的this指向上下文
setTimeout(()=>{
console.log(\'run\')
},1000)
typescript中的类
/*ts中的类*/
//es5里面的类
//1. 最简单的类
function Person(){
this.name=\'战三\';
this.age=20;
}
//实例化
var p=new Person();
console.log(p.name); //战三
//2. 构造函数和原型链里面增加方法
function Person1(name,age){
this.name=name;
this.age=age;
//run是实例方法,必须通过new完一个实例,才能调用
this.run=function(){
console.log(this.name+\'在运动\')
}
}
//类的静态方法
// Person1.getInfo=function(){
// console.log(\'我是静态方法\')
// }
//在原型链添加属性和方法
//原型链上面的属性会被多个实例共享, 构造函数不会
Person1.prototype.sex="男";
Person1.prototype.work=function(){
console.log(this.name+\'在工作\');
}
//es5的继承
//web类继承Person类 原型链+对象冒充的组合继承模式
function web(name,age) {
Person1.call(this,name,age); //对象冒充实现继承
}
web.prototype=Person1.prototype;
var w=new web(\'张三dd\',12);
w.run(); //对象冒充可以继承构造函数里面的属性和方法。
// w.work(); // 报错 对象冒充无法继承原型链上的属性和方法。
w.work(); //原型链继承可以实现
var w=new web(\'ddddd\',122);
w.run(); //对象冒充可以继承构造函数里面的属性和方法。
// w.work(); // 报错 对象冒充无法继承原型链上的属性和方法。
w.work(); //原型链继承可以实现
// var p1=new Person1();
// p1.run(); //战三在运动
// p1.work(); //战三在工作
//调用静态方法
// Person1.getInfo();//我是静态方法
/* ts中的类的写法*/
class Person5{
name:string; //属性,前面省略了public关键字
constructor(name:string) {//构造函数
this.name=name;
}
run():void{
console.log(this.name+"在跑路");
}
getName():string{
return this.name;
}
setName(name:string):void{
this.name=name;
}
}
let p1=new Person5(\'张三\');
p1.run();//张三在跑路
console.log(p1.getName());// 获取name属性
p1.setName(\'kay\');//设置name属性
console.log(p1.getName());// 重新获取name
ts的类的继承
/* ts中的类的写法*/
class Person5{
name:string; //属性,前面省略了public关键字
constructor(name:string) {//构造函数
this.name=name;
}
run():void{
console.log(this.name+"在跑路");
}
getName():string{
return this.name;
}
setName(name:string):void{
this.name=name;
}
}
//继承
class web5 extends Person5{
constructor(name:string) {
//super表示调用的父类构造函数,内部的this指向子类的的
//super指向父类的原型对象,所以定义在父类实例上的方法或属性是无法通过super调用的。
super(name);//初始化父类的构造函数
}
}
let p1=new Person5(\'张三\');
p1.run();//张三在跑路
console.log(p1.getName());// 获取name属性
p1.setName(\'kay\');//设置name属性
console.log(p1.getName());// 重新获取name
ts的类的继承方法重写
/* ts中的类的写法*/
class Person5{
name:string; //属性,前面省略了public关键字
constructor(name:string) {//构造函数
this.name=name;
}
run():void{
console.log(this.name+"在跑路");
}
getName():string{
return this.name;
}
setName(name:string):void{
this.name=name;
}
}
//继承 方法的重写
class web5 extends Person5{
constructor(name:string) {
//super表示调用的父类构造函数,内部的this指向子类的的
//super指向父类的原型对象,所以定义在父类实例上的方法或属性是无法通过super调用的。
super(name);//初始化父类的构造函数
}
run():string{
return `${this.name}在运动`
}
work():string{
return `${this.name}在工作`
}
}
let w5=new web5(\'李四\');
console.log(w5.work());
console.log(w5.run());
// let p1=new Person5(\'张三\');
// p1.run();//张三在跑路
// console.log(p1.getName());// 获取name属性
// p1.setName(\'kay\');//设置name属性
// console.log(p1.getName());// 重新获取name
类的修饰符
/* ts中的类的写法*/
/*
* 修饰符
* public 公有 在类里面。子类 类外面都能访问
* protected 保护类型 在类里面,子类里面可以访问,在类外无法访问
* private 私有 在类里面可以访问 子类 类外部都没法访问.
* 属性不加修饰符,默认是public
* */
class Person5{
public name:string; //属性,前面省略了public关键字
constructor(name:string) {//构造函数
this.name=name;
}
run():void{
console.log(this.name+"在跑路");
}
getName():string{
return this.name;
}
setName(name:string):void{
this.name=name;
}
}
//继承 方法的重写
class web5 extends Person5{
constructor(name:string) {
//super表示调用的父类构造函数,内部的this指向子类的的
//super指向父类的原型对象,所以定义在父类实例上的方法或属性是无法通过super调用的。
super(name);//初始化父类的构造函数
}
run():string{
return `${this.name}在运动`
}
work():string{
return `${this.name}在工作`
}
}
let p5=new Person5(\'ddd\');
//类外部访问
console.log(p5.name);//ddd
let w5=new web5(\'李四\');
console.log(w5.work());
console.log(w5.run());
类的静态属性 ,静态方法
/* ts中的类的写法*/
/*
* 修饰符
* public 公有 在类里面。子类 类外面都能访问
* protected 保护类型 在类里面,子类里面可以访问,在类外无法访问
* private 私有 在类里面可以访问 子类 类外部都没法访问.
* 属性不加修饰符,默认是public
* */
class Person5{
public name:string; //属性,前面省略了public关键字
constructor(name:string) {//构造函数
this.name=name;
}
run():void{
console.log(this.name+"在跑路");
}
getName():string{
return this.name;
}
setName(name:string):void{
this.name=name;
}
}
//继承 方法的重写
class web5 extends Person5{
public good:number=1222;
//定义一个静态属性
static timer:string=\'111\';
constructor(name:string) {
//super表示调用的父类构造函数,内部的this指向子类的的
//super指向父类的原型对象,所以定义在父类实例上的方法或属性是无法通过super调用的。
super(name);//初始化父类的构造函数
}
run():string{
return `${this.name}在运动`
}
work():string{
return `${this.name}在工作`
}
//定义一个静态方法 静态方法,里面没法之间调用类里面的属性 只能调用静态属性
static go():void{
// console.log(this.good);
console.log(this.timer);
}
}
let p5=new Person5(\'ddd\');
//类外部访问
console.log(p5.name);//ddd
let w5=new web5(\'李四\');
console.log(w5.work());
console.log(w5.run());
//调用静态方法
web5.go();//\'111\'
抽象 类和 多态
/*多态:父类定义一个方法不去实现,让继承它的子类去实现,每一个子类有不同的表示*/
/*多态属于继承*/
class Animal{
name:string;
constructor(name:string) {
this.name=name;
}
eat():void{
console.log(\'吃的方法\');
}
}
//子类
class Dog extends Animal{
constructor(name:string) {
super(name);//初始化父类的构造函数
}
eat():string{
return this.name+\'吃肉\';
}
}
class Cat extends Animal{
constructor(name:string) {
super(name);
}
eat():string{
return this.name+\'吃老鼠\';
}
}
/*
* typesctipt中的抽象类,他是提供其他类继承的基类,不能被实例化
* 用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体事项并且必须在派生类中事项。
* abstract抽象方法只能放在抽象类里面
* 抽象类和抽象方法用来定义标准,标准: Animal这个类要求它的子类必须包含eat方法
* */
abstract class Animal{
public name:string;
constructor(name:string) {
this.name=name;
}
abstract eat():any;
}
class Dog extends Animal {
//抽象类的子类必须实现抽象类的里面的抽象方法
constructor(name:any) {
super(name);
}
eat(){
console.log(this.name+\'吃鱼头\');
}
}
var d=new Dog(\'王公子\');
d.eat()
typescript中的接口
接口的作用,在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。接口定义了某一类所需要遵守的规范。接口不关心这些类的内部状态数据。也不关心这些类的方法的实现细节,它只规定了这批类里必须提供某些方法,提供这些方法的类可以满足实际需要。typescript中的接口类似于java.同时还增加了更灵活的接口类型,包括属性,函数,可索引和类等。
属性接口
/**接口**/
//属性接口 对json的约束
//对批量方法传入参数进行约束
//接口:行为和动作的规范,对批量方法进行约束
interface FullName {
firstName:string; //注意;结束
secondName:string;
}
function printName(name:FullName) {
//必须传入对象 firstName secondName
console.log(name.firstName+\'---\'+name.secondName);
}
var obj={
age:20,
firstName:\'张\',
secondName:\'三\'
}
printName(obj)//张---三
//接口 可选属性
interface FullName {
firstName:string;
secondName?:string;
}
function getName(name:FullName){
console.log(name)
}
getName({
firstName:\'firstName\'
})
例子: ts封装ajax
interface Config {
type:string;
url:string;
data?:string;
dataType:string;
}
function ajax(config){
var xhr=new XMLHttpRequest();
xhr.open(config.type,config.url,true);
xhr.send(config.data);
xhr.onreadystatechange=function(){
if(xhr.readyState==4 && xhr.status==200){
console.log(\'成功\')
if(config.dataType==\'json\'){
JSON.parse(xhr.responseText)
}else{
console.log(xhr.responseText);
}
}
}
}
ajax({
type:\'get\',
url:\'http://www.baidu.com\',
dataType:\'json\'
})
函数类型接口
/*
函数类接口: 对方方传入的参数,以及返回值进行约束
*/
//加密的函数类型接口
interface encrypt {
(key:string,value:string):string;
}
var md5:encrypt=function (key:string,value:string):string {
//模拟操作
return key+value;
}
console.log(md5(\'name\',\'zhangsan\'));
var sha1:encrypt=function(key:string,value:string):string{
return key+\'---\'+value;
}
可索引接口
/*
可索引接口 数组 对象的约束(不常用)
*/
//索引是number 对数组的约束
interface userArr {
[index:number]:string
}
var arr9:userArr=[\'aaa\',\'bbbb\'];
//可索引接口 对对象的约束
interface UserObj {
[index:string]:string
}
var obj9:UserObj={name:\'张三\',\'data\':\'111\'};
类类型接口
/*类类型接口:对类的约束 和抽象类有点相似*/
interface Animal10 {
name:string;
eat10(str:string):void;
}
class Dog10 implements Animal10{
name:string;
constructor(name:string) {
this.name=name;
}
eat10(){
console.log(this.name+\'吃猪头\');
}
}
var d10=new Dog10(\'小黑\');
d10.eat10();//小黑吃猪头
class Cat10 implements Animal10{
name:string;
constructor(name:string) {
this.name=name;
}
eat10(food:string) {
console.log(this.name+food)
}
}
var c10=new Cat10(\'小花\');
c10.eat10(\'猪头\');
接口的扩展、接口的继承
//接口扩展,接口可以继承接口
interface Animal11 {
eat11(): void;
}
interface Person11 extends Animal11{
work11():void;
}
class Web11 implements Person11{
public name:string;
constructor(name:string) {
this.name=name;
}
eat11(){
console.log(this.name+\'喜欢吃馒头\');
}
work11(){
console.log(this.name+\'写代码\');
}
}
var w11=new Web11(\'小李\');
w11.work11();//小李写代码
//接口扩展,接口可以继承接口
interface Animal11 {
eat11(): void;
}
interface Person11 extends Animal11{
work11():void;
}
//
class coder{
public name:string;
constructor(name:string) {
this.name=name;
}
coding(code:string){
console.log(this.name+code);
}
}
//web11继承 coder类 ,同时继承了Person11接口
class Web11 extends coder implements Person11{
constructor(name:string) {
super(name);
}
eat11(){
console.log(this.name+\'喜欢吃馒头\');
}
work11(){
console.log(this.name+\'写代码\');
}
}
var w11=new Web11(\'小李\');
w11.work11();//小李写代码
w11.coding(\'写ts代码\');//小李写ts代码
typescript中的泛型
泛型: 软件工程中,我们不仅要创建一致的定义良好的api,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持维拉的数据类型,这在创建大型系统时为提供了十分灵活的功能. 通俗理解: 泛型: 就是解决接口方法的复用性,以继对不特定数据类型的支持。
泛型类
/*泛型 可以支持不特定的数据类型 要求,传入的参数和返回的参数一致*/
//T 表示泛型 ,具体什么类型是调用这个方法的时候决定的。
function getData<T>(value:T):T{
return value;
}
//调用时输入类型
console.log(getData<number>(123)); //123
console.log(getData<string>(\'gogogo\')); //gogogo
/*泛型 可以支持不特定的数据类型 要求,传入的参数和返回的参数一致*/
//T 表示泛型 ,具体什么类型是调用这个方法的时候决定的。
// function getData<T>(value:T):T{
// return value;
//
// }
// //调用时输入类型
// console.log(getData<number>(123)); //123
// console.log(getData<string>(\'gogogo\')); //gogogo
//泛型类,比如有个最小堆算法,需要同时支持返回数字和字符串两种类型,通过类的泛型来实现。
class MinClass<T>{
public list:T[]=[];
add(value:T):void{
this.list.push(value);
}
min():T{
var minNum=this.list[0];
for(var i=0;i<this.list.length;i++){
if(minNum>this.list[i]){
minNum=this.list[i];
}
}
return minNum;
}
}
var m1=new MinClass<number>(); /*实例化类,并且制定了类的类型是number*/
m1.add(2);
m1.add(7);
m1.add(444);
console.log(m1.min()); //输出最小是2
var m2=new MinClass<string>(); /*实例化类,并且制定了类的类型是string*/
m2.add(\'a\');
m2.add(\'g\');
m2.add(\'v\');
console.log(m2.min()); //输出最小是\'a\'
泛型函数接口
/*泛型函数接口*/
// 第一种写法
interface ConfigFn {
<T>(value:T):T;
}
var getData:ConfigFn=function<T>(value:T):T{
return value;
}
console.log(getData<string>(\'张三\'));// 张三
console.log(getData<number>(1111)); //1111
//第二种写法
interface ConfigFn<T>{
(value:T):T;
}
function getData<T>(value:T):T{
return value;
}
//选择string类型
var myGetData:ConfigFn<string>=getData;
//调用
console.log(myGetData(\'20\'));//\'20\'
泛型类实例Db类
/*
* 定义一个user的类的这个类的作用就是映射数据库字段
* 然后定义一个MysqlDb的类这个类用于操作数据库
* 然后把User类作为参数传入到MysqlDb中
* */
//把类作为参数来约束数据传入类型
class User{
username:string |undefined;
password: string| undefined;
}
class MysqlDb{
add(user:User):boolean{
console.log(user);
return true;
}
}
var u=new User();
u.username=\'张三\';
u.password=\'12233\';
var Db=new MysqlDb();
Db.add(u);
/*
* 定义一个user的类的这个类的作用就是映射数据库字段
* 然后定义一个MysqlDb的类这个类用于操作数据库
* 然后把User类作为参数传入到MysqlDb中
* */
//把类作为参数来约束数据传入类型
// class User{
// username:string |undefined;
// password: string| undefined;
// }
// class MysqlDb{
// add(user:User):boolean{
// console.log(user);
// return true;
// }
// }
// var u=new User();
// u.username=\'张三\';
// u.password=\'12233\';
//
// var Db=new MysqlDb();
// Db.add(u);
//操作数据库的泛型类
class MysqlDb<T>{
//增添操作
add(info:T):boolean{
console.log(info);
return true;
}
//更新操作
updated(info:T,id:number):boolean{
console.log(info);
console.log(id);
return true;
}
}
//想给User表增加数据
//1.定义一个User类 和数据库进行映射
class User{
username:string | undefined;
password: string | undefined;
}
var u=new User();
u.username=\'钩子\';
u.password=\'1111\';
var Db1=new MysqlDb<User>();
console.log(Db1.add(u));//User { username: \'钩子\', password: \'1111\' } true
//定义文章类
class ArticleCate{
title: string | undefined;
desc:string | undefined;
status: number | undefined;
constructor(params:{
title: string | undefined;
desc:string | undefined;
status?: number | undefined;
}) {
this.title=params.title;
this.desc=params.desc;
this.status=params.status;
}
}
//实例化文章类
var a1=new ArticleCate({
title:\'分类\',
desc:\'1111\'
});
//实例化数据库类 类型检测ArticleCate
var Db2=new MysqlDb<ArticleCate>();
//添加操作
console.log(Db2.add(a1));//ArticleCate { title: \'分类\', desc: \'1111\', status: undefined } true
//更新操作
var a2=new ArticleCate({
title:\'分类dddd\',
desc:\'222\'
});
a2.status=1;
var Db3=new MysqlDb<ArticleCate>();
console.log(Db3.updated(a2,12));//ArticleCate { title: \'分类dddd\', desc: \'222\', status: 1 } 12 true
/*
综合应用
ts封装统一操作 mysql Monggodb Mssql的底层库
功能: 定义一个操作数据库的库,支持mysql Mssql MongoDb
要求: mysql msSql mongoDb功能一样 都有 add update delete get方法
注意: 约束统一的规范,以及代码重用
解决方案: 需要越苏规范所以要定义接口,需要代码重用所以用到泛型
1.接口: 在面向对象的编程中,接口是一种规范的定义,它定义行为和动作的规范。
2.泛型: 通俗理解: 泛型就是解决类接口方法的复用性。
*/
interface DBI<T> {
add(info:T):boolean;
update(info:T,id:number):boolean;
delete(id:number):boolean;
get(id:number):any[];
}
//定义一个操作mysql数据库的类 注意:要实现泛型接口 这个类也应该是一个泛型类
class MysqlDb<T> implements DBI<T>{
constructor() {
console.log(\'数据库建立连接\');
}
add(info: T): boolean {
console.log(info);
return true;
}
delete(id: number): boolean {
return false;
}
get(id: number): any[] {
return [];
}
update(info: T, id: number): boolean {
return false;
}
}
//定义一个操作mssql数据库的类
class MssqlDb<T> implements DBI<T>{
add(info: T): boolean {
console.log(info);
return true;
}
delete(id: number): boolean {
return true;
}
get(id: number): any[] {
var list=[
{
title:\'1111\',
desc:\'xxx\'
},
{
title:\'12221\',
desc:\'dmmmdld\'
},
]
return list;
}
update(info: T, id: number): boolean {
return false;
}
}
//操作用户表 定义一个User类和数据表的映射
class User{
username:string | undefined;
password: string | undefined;
}
var u=new User();
u.username=\'ddd\';
u.password=\'12344\';
var oMssql=new MssqlDb<User>();
oMssql.add(u); //User { username: \'ddd\', password: \'12344\' }
var data=oMssql.get(2);
console.log(data)//[ { title: \'1111\', desc: \'xxx\' },{ title: \'12221\', desc: \'dmmmdld\' } ]
typescript模块
模块的概念(自己理解): 我们可以把一些公共的功能单独抽离成一个文件作为一个模块。模块里面的变量函数类等默认是私有的,如果我们要在外部访问模块里面的数据(变量 函数 类),我们需要通过export暴露模块里面的数据
(变量 函数 类)。暴露后我们通过import引入模块可以使用模块里面暴露的数据(变量 函数 类)
//db.ts
//第一种暴露方式
export var dbUrl=\'xxxxx\';
export function getData(){
console.log(\'获取数据库的数据\')
return [
{
title:\'111122\'
},
{
title:\'122ddddd\'
}
]
}
export function save() {
console.log(\'保存数据成功\');
}
//index.ts中接收
import {getData,save} from \'../modules/db\'
//export default getData; //default只能调用一次
getData();//获取数据库的数据
save();//保存数据成功
//第二种方式
var dbUrl=\'xxxxx\';
function getData(){
console.log(\'获取数据库的数据\')
return [
{
title:\'111122\'
},
{
title:\'122ddddd\'
}
]
}
function save() {
console.log(\'保存数据成功\');
}
export {dbUrl,getData,save};
//index.ts中接收
import {getData,save} from \'../modules/db\'
getData();//获取数据库的数据
save();//保存数据成功
//接收default
import getData from \'./modules/db\'
getData();
封装类似Mongoose风格的类库
db.ts
interface DBI<T> {
add(info:T):boolean;
update(info:T,id:number):boolean;
delete(id:number):boolean;
get(id:number):any[];
}
//定义一个操作mysql数据库的类 注意:要实现泛型接口 这个类也应该是一个泛型类
export class MysqlDb<T> implements DBI<T>{
constructor() {
console.log(\'数据库建立连接\');
}
add(info: T): boolean {
console.log(info);
return true;
}
delete(id: number): boolean {
return false;
}
get(id: number): any[] {
return [];
}
update(info: T, id: number): boolean {
return false;
}
}
//定义一个操作mssql数据库的类
export class MssqlDb<T> implements DBI<T>{
add(info: T): boolean {
console.log(info);
return true;
}
delete(id: number): boolean {
return true;
}
get(id: number): any[] {
var list=[
{
title:\'1111\',
desc:\'xxx\'
},
{
title:\'12221\',
desc:\'dmmmdld\'
},
]
return list;
}
update(info: T, id: number): boolean {
return false;
}
}
Article.ts
import {MssqlDb} from "../modules/db";
class ArticleClass{
title:string | undefined;
desc: string | undefined;
}
var ArticleModel=new MssqlDb<ArticleClass>();
export {
ArticleClass,ArticleModel
}
User.ts
import {MssqlDb} from "../modules/db";
//操作用户表 定义一个User类和数据表的映射
class UserClass{
username:string | undefined;
password: string | undefined;
}
var UserModel=new MssqlDb<UserClass>();
export {
UserClass,UserModel
}
// u.username=\'ddd\';
// u.password=\'12344\';
// var oMssql=new MssqlDb<UserClass>();
// oMssql.add(u); //User { username: \'ddd\', password: \'12344\' }
// var data=oMssql.get(2);
// console.log(data)//[ { title: \'1111\', desc: \'xxx\' },{ title: \'12221\', desc: \'dmmmdld\' } ]
index.js
import {UserClass,UserModel} from "../model/user";
//增加数据
var u=new UserClass();
u.username=\'张三\';
u.password=\'112222\';
UserModel.add(u);
//获取user表数据
var res=UserModel.get(122);
console.log(res);
import {ArticleModel,ArticleClass} from "../model/article";
//获取文章的数据
var aRes=ArticleModel.get(1);
console.log(aRes);
typescript命名空间
在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似的功能的函数、类、接口等放置到命名空间内。
- 命名空间: 内部模块,主要用于组织代码,避免命名冲突
- 模块:ts的外部模块的简称,侧重代码的复用,一个模块里可能会有多个命名空间。
//命名空间 作用域的方法和变量是私有的,需要export才能导出使用
//a.ts 存放命名空间
export namespace A{
interface Animal {
name:string;
eat():void;
}
export class Dog implements Animal{
name:string;
constructor(theName:string) {
this.name=theName
}
eat(){
console.log(`${this.name}吃狗粮`)
}
}
export class Cat implements Animal{
name:string;
constructor(theName:string) {
this.name=theName;
}
eat(){
console.log(`${this.name}吃猫粮`)
}
}
}
export namespace B{
interface Animal {
name:string;
eat():void;
}
export class Dog implements Animal{
name:string;
constructor(theName:string) {
this.name=theName
}
eat(){
console.log(`${this.name}吃狗粮`)
}
}
export class Cat implements Animal{
name:string;
constructor(theName:string) {
this.name=theName;
}
eat(){
console.log(`${this.name}吃猫粮`)
}
}
}
// console.log(1111);
//1.ts
//导入命名空间A,B
import {A,B} from \'../modules/a\'
//命名空间外部使用 A的类
var d=new A.Dog(\'大黄\');
d.eat();//大黄吃狗粮
//命名空间外部使用B的类
var c=new B.Cat(\'喵喵折\');
c.eat();//喵喵折吃猫粮
demo结果
typescript装饰器
装饰器: 装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或者参数上,可以修改类的行为。
通俗来讲: 装饰器就是一个方法,可以注入到类,方法,属性参数上来扩展类,属性,方法,参数的功能。
常见的装饰器有: 类装饰器,属性装饰器,方法装饰器,参数装饰器
装饰器的写法: 普通装饰器(无法传参) 装饰器工厂(可传参)
类装饰器
类装饰器: 类装饰器在类声明之前被声明(紧靠着声明) 类装饰器应用于类构造函数,可以用来监视,修改或替换类定义,并传入一个参数。
/* 类装饰器*/
function logClass(params:any) {
//params就是当前类
console.log(params)// [Function: HttpClient]
params.prototype.apiUrl=\'动态扩展属性\';
//扩展动态方法
params.prototype.run=function(){
console.log(\'我是一个run方法\');
}
}
//调用装饰器用@ 普通装饰器无法传参
@logClass
class HttpClient{
constructor() {
}
getData(){
}
}
var http:any=new HttpClient();
console.log(http.apiUrl);//动态扩展属性
http.run();//我是一个run方法
/* 类装饰器*/
/*
* 1.2类装饰器,装饰器工厂(可传参)
* */
function logClass(params:string) {
return function(target:any){
console.log(target);//把类 传参给
// console.log(params); //www.baidu.com
target.prototype.apiUrl=params;
}
}
//调用装饰器用@
@logClass(\'www.baidu.com\')
class HttpClient{
constructor() {
}
getData(){
}
}
var http:any=new HttpClient();
console.log(http.apiUrl); //www.baidu.com
/*
类装饰器
* 重载构造函数的例子
类构造器表达式会在运行时当做函数被调用,类的沟站函数作为其唯一的参数。
如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
* */
function logClass(target:any){
console.log(target);
return class extends target{
apiUrl:any=\'我是修改后的数据\';
getData(){
this.apiUrl=this.apiUrl+\'----\';
console.log(this.apiUrl);
}
}
}
@logClass
class HttpClient{
public apiUrl:string | undefined;
constructor() {
this.apiUrl=\'我是构造函数里面的apiUrl\'
}
getData(){
console.log(this.apiUrl);
}
}
var http=new HttpClient();
http.getData();//我是修改后的数据----
属性装饰器
属性装饰器表达式会在运行时,当做函数被调用,传入下列两个参数
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
- 成员的名字
/*
类装饰器
* 重载构造函数的例子
类构造器表达式会在运行时当做函数被调用,类的沟站函数作为其唯一的参数。
如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
* */
//视频时间 20.06
//类装饰器
function logClass(params:string){
return function (target:any) {
// console.log(target);
// console.log(params);
}
}
//属性装饰器
function logProperty(params:any){
return function(target:any,attr:any){
console.log(target) //HttpClient { getData: [Function] }
console.log(attr) //apiUrl
target[attr]=params;
}
}
@logClass(\'xxxxx\')
class HttpClient{
@logProperty(\'xxxsssss\')
public apiUrl:string | undefined;
constructor() {
}
getData(){
console.log(this.apiUrl)//xxxsssss
}
}
var http=new HttpClient();
http.getData();//我是修改后的数据----
方法装饰器
他会应用到方法的属性描述符上,可以用来监视,修改或者替换方法定义。
/*
方法装饰器 它会接应应用到方法的属性的描述符上,可以用来监视,修改或者替换方法的定义
方法的装饰会在运行时传入下列3个参数
1.对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
2.成员的名字
3.成员的属性描述符
*/
//方法装饰器
function logMethod(params:any){
return function (target:any,methodName:any,desc:any) {
console.log(target); //HttpClient { getData: [Function] }
console.log(methodName); //getData
console.log(desc); // { value: [Function],writable: true, enumerable: true,configurable: true }
target.apiUrl=\'mssmmsmsm\';
target.run=function () {
console.log(\'run\')
}
}
}
class HttpClient{
public url:any | undefined;
constructor() {
}
@logMethod(\'xxxx\')
getData(){
console.log(this.url);
}
}
var http:any=new HttpClient();
console.log(http.apiUrl);
http.run();
//方法装饰器 修改getData方法
function logMethod(params: any) {
console.log(params)
return function (target: any, methodName: any, desc: any) {
console.log(target); //HttpClient { getData: [Function] }
console.log(methodName); //getData
console.log(desc.value); //方法定义
//修改装饰器的方法,把装饰器方法里面传入的所有参赛改为string类型
//保存当前的方法
var oMethods=desc.value;
//替换
desc.value=function (...args:any[]) {
args=args.map((value)=>{
return String(value)
})
console.log(args);
//修改方法 对象冒充
oMethods.apply(this,args);
}
}
}
class HttpClient {
public url: any | undefined;
constructor() {
}
@logMethod(\'xxxx\')
getData(...args:any[]) {
console.log(args)
console.log(\'我是getData中的方法\');
}
}
var http: any = new HttpClient();
http.getData(\'123\',\'xxx\');//[ \'123\', \'xxx\' ]
方法参数装饰器
参数装饰器表达式会在运行时当做函数直接调用,可以使用参数装饰器为类的原型增加一些元素数据,传入下列3个参数
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 参数的名字
- 参数在函数参数列表的索引。
//方法参数
function logParams(params:any) {
return function (target: any, methodName: any, paramsIndex: any) {
console.log(params)
console.log(target);
console.log(methodName);
console.log(paramsIndex);
target.apiUrl=params;
}
}
class HttpClient {
public url: any | undefined;
constructor() {
}
getData(@logParams(\'uuiddddddddd\') uuid: any) {
console.log(\'我是getData里面的方法\')
console.log(uuid+\'----\');
}
}
//实例化
var http:any = new HttpClient();
http.getData(11111)
console.log(http.apiUrl);
装饰器的执行顺序
属性>方法>方法参数>类 如果有多个同样的装饰器,它会优先执行后面的(从里到外的执行顺序)
请发表评论