typeScript

javascript/jquery

浏览数:271

2020-7-16

*面向对象:
通过extends实现继承
通过public等访问修饰符实现封装
通过方法覆盖实现多态*

注意事项:
私有private:当成员被标记成private时,它就不能在声明它的类的外部访问
保护protected:protected成员在派生类中仍然可以访问
只读readonly:只读属性必须在声明时或构造函数里被初始化
参数属性:给构造函数的参数加上修饰符 能够定义并初始化一个成员属性

class Animal {
    constructor(private name:string){//定义name属性并将构造参赋值给他
    }
}

存取器:当获取和设置属性时 有额外逻辑时可以使用存取器(又称getter,setter)

class Employee {
    private _fullName: string = 'Mike James'
    get fullName(): string {
        return this._fullName
    }
    set fullName(newName: string){
        console.log('你修改了用户名')
        this._fullName = newName
    }
}
// 类型注解
// let name1: string;
// name1 = 'tom'
// name1 = 123 wrong
let name1: string|object;
name1 = 'tom'
name1 = {name:'fe'}
// 类型推论
let name2 = 'jerry'
// 数组类型
let names: string[]
names=['qwe']
// 任意类型
let foo:any = 'xx'
foo = 123
// 任意类型也可用于数组
let list: any[] = [1,true,'free']
list[1] = 100
// 函数中的类型
// 同时设置了返回值类型
function greeting(person:string):string{
    return 'hello'+ person
}
function greeting2(person: string): void {
    
}
greeting('tom')
//常见内置类型  void没有返回值
// string,number,boolean,void,any
//函数
// 此处name和age是必填参数
// 如果要变为可选参数 加上?
// 可选参数在必选参数的后面
function sayHello(name:string,age:number=20,addr?:string):string{
    return '你好:'+ name + '' + age
}
sayHello('jerry')
sayHello('jerry', 36)
// 函数的重载:以参数数量或类型区分多个同名参数
// 如果一个函数,将来的参数的类型或者参数的个数,或者返回值的类型 如果不同,可以认为是另外一个重载, 
// 它的函数的方法名可以是相同的
// 参数的数量或者类型或者返回值的类型不同, 函数名却相同
// 先声明 在实现
function info(a:{name:string}):string
function info(a:string):object
function info(a: {name:string}|string): any {
    if (typeof a === "object"){
        return a.name
    } else {
        return {name:a}
    }
}
console.log(info({name:"tom"}))
console.log(info("tom"))

// Class面向对象
// class Shape {
//     area: number
//     protected color: string
//     constructor(color:string,width:number,height:number){
//         this.area = width*height
//         this.color = color
//     }
//     shoutout(){
//         return "I'm"+this.color+'width an area of'+this.area+'cm squared'
//     }
// }
class Shape {
    // area: number
    // protected color: string
    constructor(protected color: string, protected width: number, protected height: number) {
        // this.area = width * height
        this.color = color
    }

    // 类似于vue的计算属性   变相实现只读的属性
    get area(){
        return this.width*this.height
    }
    shoutout() {
        return "I'm" + this.color + 'width an area of' + this.area + 'cm squared'
    }
}
class Square extends Shape {
    constructor(color: string, side: number){
        super(color,side,side)
        console.log(this.color)
    }
    // 覆盖
    shoutout(){
        return "我是"+this.color+"面积是"+this.area+"平方厘米"
    }
}
const square= new Square('blue',2)
console.log(square.shoutout())

接口

接口仅约束结构,不要求实现 使用更简单

interface Person{
    firstName:string,
    lastName:string
}

function greeting(person:Person){
    return 'Hello,'+ person.firstName+''+person.lastName
}
const user = {firstName: 'Jane',lastName: 'User'}
console.log(user)
console.log(greeting(user))

泛型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型 而是在使用的时候再指定类型的一种特性

// 不使用泛型
interface Result {
    ok:0|1;
    data: Feature
}


// 使用泛型
interface Result<T> {
    ok:0|1;
    data:T[]
}

范例:使用泛型约束接口返回类型

function getData<T>(): Result<T> {
    const data:any[] = [
        { id: 1, name: '3ere', version: '1.2' },
        { id: 2, name: 'fffff', version: '2.2' }
    ]
    return {ok:1,data}
}

// 使用接口
created(){
    this.features = getData<Feature>().data
}

装饰器

*装饰器实际上是工厂函数 传一个对象,输出处理后的新对象
典型应用是组件装饰器@Component*

@Component
export default class Hello extends Vue

若不加小括号,则装饰器下面紧挨着的对象就是目标对象

@Component({
    props:{//属性也可以在这里配置
        name:{
            type:String,
            default:'匿名'
        }
    }
})
export default class Hello extends Vue {}

类似的还有App.vue中配置的依赖组件选项components

范例: 事件处理@Emit

新增特性时派发事件通知父组件,Hello.vue

// 通知父类新增事件,若未指定事件名则函数名作为事件名(羊肉串形式)
 @Emit()
 private addFeature(event:any){
    const feature = {name:event.target.value,id:this.features.length+1};
    this.features.push(feature)
    event.target.value = ""
    return feature//返回值作为事件参数
 }

父组件接收并处理 App.vue

<Hello @add-feature="onAddFeature"></Hello>
export default class App extends Vue{
    private onAddFeature(feature:any) {
        console.log("新增特性:"+feature.name)
    }
}

范例:属性变更检测@Watch, sayHello.vue

// 
@Watch('msg')
onRouteChange(val:string,oldVal:any){
    console.log(val,oldVal)
}

在vue中的实际使用

在创建项目的时候选typeScript

App.vue

<template>
  <div id="app">
    <!-- <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/> -->
    <Hello msg="Welcome tottt Your Vue.js + TypeScript App" @add-feature="xxx"/>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from './components/HelloWorld.vue';
import Hello from './components/Hello.vue';

@Component({
  components: {
    HelloWorld,
    Hello
  },
})
export default class App extends Vue {
  xxx(){
    
  }
}
</script>

<style>

</style>

组件Hello.vue

<template>
    <div>
        <div>
            <input type="text" placeholder="输入新特性" @keyup.enter="addFeature">
        </div>
        {{msg}}
        <ul>
            <li v-for="feature in features" :key="feature.id">{{feature.name}}</li>
            <li>{{count}}</li>
        </ul>
    </div>
</template>

<script lang="ts">
    import {Component,Prop,Vue,Emit,Watch} from 'vue-property-decorator'
    //接口中只需要定义结构  不需要初始化
    interface Feature{
            id:number;
            name: string;
            version:string
    }
    interface Result<T> {
    ok:0|1;
    data:T[]
    }
    function getData<T>(): Result<T> {
    const data:any[] = [
        { id: 1, name: '3ere', version: '1.2' },
        { id: 2, name: 'fffff', version: '2.2' }
    ]
    return {ok:1,data}
}
    @Component({
    props:{//属性也可以在这里配置
        name:{
            type:String,
            default:'匿名'
        }
    }
})
    export default class Hello extends Vue{
        // 函数类型去使用的
        // 类型控制 一个是用于vue编译器的 一个用于ts编译器
        @Prop({required: true,type:String}) msg!: string;
        // data中的值
        // private features = ['类型注解','blabla']
        // private features:Feature[] = [{id:1,name:'类型注解',version:'1.0'}]
        private features!:Feature[];
        @Watch('features',{deep:true})
        onRouteChange(val:string,oldVal:any){
            console.log(val,oldVal)
        }
        @Emit()
        private addFeature(event:any){
            const feature = {name:event.target.value,id:this.features.length+1,version:'1.0'}
            this.features.push(feature)
            event.target.value= feature
            return event.target.value
        }
        // get count(){
        //     return this.features.length
        // }
        // 如果要让继承的类访问 protected
        // 如果都能访问public

        // 生命周期
        private created(){
            setTimeout(()=>{
                this.features.push({id:2,name:'sss注解',version:'2.0'})
            },1000)
            // 约束返回的结果是Result类型 里面的data得是Feature类型  两层约束
            // this.features = getData<Result<Feature>>().data
        }
    }
</script>

<style scoped>

</style>

作者:yang