typescript 的认识3

// 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.装饰器的执行顺序
// 类装饰器可以有多个,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值