// 10.案例
// $.ajax({
// type: "GET",
// url: "test.json",
// data: {username:$("#username").val(), content:$("#content").val()}
// });
interface Config {
type: string;
url: string;
data?: string;
dataType: string;
}
function ajax(config: Config) {
var xhr = new XMLHttpRequest();
xhr.open('get', config.url, true) //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',
data: 'name=zhangsan',
url: 'http://www.baidu.com',
dataType: 'json'
})
// 11.函数类型接口: 对方法传入的参数 以及返回值进行约束
//加密的函数类型接口
interface encrypt {
//函数类型加快,不需要加function,直接传参数
(key: string, value: string): string;
}
var md5: encrypt = function (key: string, value: string): string {
//模拟操作
return key + value;
}
md5("name", "zhangsan")
// 12.可索引接口: 数组、对象的约束 (不常用)
// ts定义数组的方式
var a2: number[] = [11, 234, 44444]
var a1: string[] = ['111', '11234']
// 对 数组的约束
interface UserArr {
//index是数组索引,必须为number,值是string
[index: number]: string;
}
var arr5: UserArr = ["234", "werf"]
// 对 对象的约束
interface UserObj {
[index: string]: string
}
var arrObj: UserObj = { name: "chenf" }
// 13.类类型接口: 对类的约束 和 抽象类有点相似
interface Animal {
name: string;
eat(str: string): void;
}
class Dog11 implements Animal {
name: string;
constructor(name: string) {
this.name = name
}
eat() {
console.log(this.name + "吃骨头");
}
}
var d = new Dog('小黑');
d.eat();
// 14.泛型类:比如有个最小堆算法,需要同时支持返回数字 和 字符串 两种类型,通过泛型类实现
// 通俗理解:解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)
// 当然,我们也可以写成any,只是性能 没泛型高
class MinClass {
public list: number[] = []
add(num: number) {
this.list.push(num)
}
min(): number {
var minNum = this.list[0];
for (let i = 0; i < this.list.length; i++) {
if (minNum > this.list[i])
minNum = this.list[i]
}
return minNum;
}
}
var m = new MinClass();
m.add(3);
m.add(13);
m.add(123);
m.add(1233);
alert(m.min())
// ts类的泛型:
class MinClass1<T>{
public list: T[] = [];
add(value: T): void {
this.list.push(value);
}
min(): T {
var minNum = this.list[0];
for (let i = 0; i < this.list.length; i++) {
if (minNum > this.list[i])
minNum = this.list[i]
}
return minNum;
}
}
var m1 = new MinClass1<number>(); /* 实例化类,并指定类的T代表的类型是number */
// m1.add("string"); //报错
m1.add(1); //正确
m1.add(23)
m1.add(234)
m1.add(245)
alert(m1.min())
var m2 = new MinClass1<string>();
m2.add('a')
m2.add('b')
m2.add('c')
m2.add('d')
// 15.泛型接口
// 函数类型接口
interface ConfigFn {
(value1: string, value2: string): string;
}
var setData1: ConfigFn = function (value1: string, value2: string): string {
return value1 + value2;
}
setData1('name', 'zhangsan')
// 第一种定义方法:泛型接口
interface ConfigFx {
<T>(value: T): T;
}
var getData: ConfigFx = function <T>(value: T): T {
return value;
}
// 调用
getData<string>('张三');
// getData<string>(2324); //报错
// 第二种定义方法:泛型接口
interface MyConfigFx<T> {
(value: T): T;
}
function mygetData<T>(value: T): T {
return value;
}
var myGetData: MyConfigFx<string> = getData;
myGetData('20')
// myGetData(3) //报错
//把类作为参数类型的泛型类
/**
* 定义一个User的类:用来映射数据库字段
* 然后定义一个MysqlDb类用于操作数据库
* 然后把User类作为参数传入到MysqlDb中
*
* var user = new User({
* username: "张三",
* password: '123456'
* })
*
* var Db = new MysqlDb();
* Db.add(user);
*
*/
class User {
username: string | undefined; //public可省略
password: string | undefined;
}
class MysqlDb {
add(user: User): boolean {
return true;
}
}
var u = new User();
u.username = '张三'
u.password = '134444'
var Db = new MysqlDb();
Db.add(u)
// 现在又想给文章分类表加入数据, 现在我们改成泛型类
// 操作数据库的泛型类
class MysqlDb1<T>{
add(info: T): boolean {
return true;
}
}
// 想给User表增加数据
// 定义一个User类和数据库映射
class User1 {
username: string | undefined; //public可省略
password: string | undefined;
}
var u1 = new User1();
u1.username = '李四'
u1.password = '12314'
var db = new MysqlDb1<User>(); //对传入的数据进行校验
// db.add("chenfg") //报错
db.add(u1)
// 定义一个Article类 和数据库进行映射
class Article {
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 art = new Article({
title: '分类',
desc: '111'
})
var db1 = new MysqlDb1<Article>();
db1.add(art)
/**
* 案例:定义一个操作数据库的库 支持mysql mongodb mssql
* 要求:都有 add update delete get 方法
* 注意:约束统一规范, 代码重用
* a. 约束规定:需要定义接口
* b. 代码重用:需要定义泛型
*/
interface DBI<T> {
add(info: T): boolean;
update(info: T, id: number): boolean;
delete(id: number): boolean;
get(id: number): any[];
}
// 定义一个操作mysql数据库的类, 要实现泛型接口,这个类也需要是泛型类
class MysqlDb2<T> implements DBI<T>{
add(info: T): boolean {
throw new Error("Method not implemented.")
}
update(info: T, id: number): boolean {
throw new Error("Method not implemented.")
}
delete(id: number): boolean {
throw new Error("Method not implemented.")
}
get(id: number): any[] {
throw new Error("Method not implemented.")
}
}
class MsSqlDb<T> implements DBI<T>{
add(info: T): boolean {
console.log(info);
return true;
}
update(info: T, id: number): boolean {
throw new Error("Method not implemented.")
}
delete(id: number): boolean {
throw new Error("Method not implemented.")
}
get(id: number): any[] {
throw new Error("Method not implemented.")
}
}
class User11 {
username: string | undefined; //public可省略
password: string | undefined;
}
var u11 = new User11();
u11.username = '李四'
u11.password = '12314'
var oMysql = new MysqlDb2<User11>();
oMysql.add(u11)
var oMssql = new MsSqlDb<User11>();
oMssql.add(u11);
// 16.命名空间和模块的区别: Typescript的命名空间可以将代码包裹起来,只对外暴露需要在外部
// 访问的对象。命名空间内的对象通过export导出
/**
* 命名空间和模块的区别:
* 命名空间: 内部模块,主要用来组织代码,避免命名冲突
* 模块: ts的外部模块的简称,侧重代码的复用,一个模块里可能有多个命名空间
*/
namespace A {
interface Animal {
}
export class Dog implements Animal { // 命名空间里的是私有的,需要使用export暴露
}
}
namespace B {
interface Animal {
}
export class Dog implements Animal {
}
}
//调用
var dd = new A.Dog()
// 引入模块命名空间
import { A1, B1 } from './modules/a'
// 17.装饰器
/**
* 装饰器:是一种特殊类型的声明,它能够被附加到类声明,方法,属性和参数上,可以修改类的行为
* 其实就是一个 方法, 可以注入到类,方法,属性参数上来扩展类,属性,方法,参数的功能。
*
* 常见的装饰器有:类装饰器,方法装饰器,参数装饰器
* 写法: 普通装饰器(无法传参)、装饰器工厂(可传参)
*
*/
// 17.1 类装饰器: 在类声明之前被声明。装饰器应用与类构造函数,可以用来监视,修改或替换类定义,
// 17.2普通装饰器
function logclass(params: any) {
console.log(params);
//params:就是代表当前类
//扩展属性
params.prototype.apiUrl = "动态扩展的属性";
//扩张方法
params.prototype.run = function (params: any) {
console.log("我是一个run方法")
}
}
@logclass //调用装饰器, 在不修改类的情况下,使用装饰器来动态扩展类的功能
class HttpClient {
name: string;
constructor(name: string) {
this.name = name;
}
getData() {
}
}
var httpClient: any = new HttpClient("1");
// 打印看有没有apiUrl
console.log(httpClient.apiUrl)
// 17.3 装饰器工厂(可传参)
function logclass1(params: string) {
// target:就是使用这个装饰器当前的类
return function (target: any) {
console.log(target);
console.log(params);
//扩张target的属性
target.prototype.apiUrl = params
}
}
@logclass1("hello ts扩展的属性")
class HttpClient1 {
getData() {
}
}
var http: any = new HttpClient1();
console.log(http.apiUrl);
// 18.类装饰器例子: 重载构造函数的例子
/**
* 类装饰器表达式会在运行时当作函数被调用,类的构造函数作为唯一的参数
* 如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明
*/
//装饰器
function logClass(target: any) {
console.log(target);
return class extends target {
apiUrl: any = '我是修改后的数据'
getData(){
console.log(this.apiUrl + 'getdata')
}
}
}
@logclass
class HttpClient2 {
public apiUrl: string | undefined;
constructor() {
this.apiUrl = '我是构造函数里面的apiUrl';
}
getData() {
console.log(this.apiUrl);
}
}
var http2 = new HttpClient2();
http2.getData(); //打印 我是构造函数里面的apiUrl。加上了类装饰器后,打印: 我是修改后的数据
// 19.属性装饰器例子
/**
* 属性装饰器表达式会在运行时当作函数被调用,传入下列两个参数;
* 1.对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
* 2.成员的名字
*/
//类装饰器
function logclassS(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);
console.log(attr);
target.attr = params; //target[attr] = params;
}
}
@logclassS("hello ts扩展的属性")
class HttpClientS {
@logProperty('http://www.baidu.com')
public url:any | undefined;
constructor(){
}
getData() {
console.log(this.url);
}
}
var httpS:any = new HttpClientS();
// 20.方法装饰器
/**
* 会被应用到方法的 属性描述上,可以用来监视,修改或者替换方法定义
* 方法装饰器会在运行是传入下列3个参数:
* 1.对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
* 2.成员的名字
* 3.成员的属性符描述
*
*/
//方法装饰器一
function get(params:any) {
return function (target:any, methodName:any, desc:any) {
console.log(target);
console.log(methodName);
console.log(desc);
target.apiUrl = 'xxx';
target.run = function () {
console.log('run');
}
}
}
class HttpClientG {
public url:any | undefined;
constructor(){
}
@get('http://www.baidu.com')
getData() {
console.log(this.url);
}
}
var httpg:any = new HttpClientG();
console.log(http.apiUrl);
httpg.run()
//方法装饰器二
function get2(params:any) {
return function (target:any, methodName:any, desc:any) {
console.log(target);
console.log(methodName);
console.log(desc);
console.log(desc.value); //desc.value就是当前方法getData里面的东西
// 修改装饰器的方法 把装饰器方法里面传入的所有参数改为string类型
// 1.保存当前的方法
var oMethod = desc.value;
desc.value = function (...args:any[]) {
//map遍历数组,根据函数操作数组,返回新的数组
args = args.map((value) =>{
return String(value)
})
console.log(args); //我们把方法替换了
//使用对象冒充的方式
oMethod.apply(this, args)
}
}
}
class HttpClientG2 {
public url:any | undefined;
constructor(){
}
@get('http://www.baidu.com')
getData(...args:any[]) {
console.log(args);
console.log('我是getData里面的方法');
}
}
var httpg2:any = new HttpClientG2();
httpg2.getData(12,'xxxxx') //打印 ["12", "xxxxx"]
// 21.方法参数装饰器
/**
* 参数装饰器表达式会在运行时当作函数被调用, 可以使用参数装饰器作为类的原型增加一些元数据,传入下列3个参数
* 1.对于静态成员来时时类的构造函数,对于实例成员来说时类的原型
* 2.参数的名字
* 3.参数在函数参数列表中的索引。
*/
function logParams(params:any) {
return function (target:any, methodName:any, paramsIndex:any) {
console.log(params)
console.log(target);
console.log(params);
console.log(paramsIndex);
//使用
target.apiUrl = params;
}
}
class HttpClientParams {
public url:any | undefined;
constructor(){
}
getData(@logParams('uuid') uuid:any) {
console.log(uuid)
}
}
var httpParams:any = new HttpClientParams()
httpParams.getData(1343456)
httpParams.apiUrl;
// 22.装饰器的执行顺序
// 类装饰器可以有多个,
typescript 的认识3
最新推荐文章于 2024-07-21 18:22:34 发布