cli3脚手架搭建一个基于ts的基础脚手架的方法(2)

<template> <p>特性数量:{{count}}</p> </template> <script lang="ts"> export default class Demo extends Vue { // 定义 getter 作为计算属性 get count () { return this.features.length; } } </script>

接口

接口仅约束结构,不要求实现

interface Person { firstName: string; lastName: string; } function greeting (person: Person) { return `Hello, ${person.firstName} ${person.lastName}`; } const user = {firstName: 'Jane', lastName: 'user'}; console.log(greeting(user));

案例:vue demo,声明接口类型约束数据结构

<template> <li v-for="feature in features" :key="feature.id">{{feature.name}}</li> </template> <script lang="ts"> // 定义一个接口约束feature的数据结构 interface Feature { id: number; name: string; } export default class Demo extends Vue { private features: Feature[]; constructor () { super(); this.features = [ {id: 1, name: '类型注解'}, {id: 2, name: '类型推论'}, {id: 3, name: '编译型语言'} ] } } </script>

泛型

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

interface Result<T> { data: T; } // 不使用泛型 interface Result { data: Feature[]; }

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

function getData<T>(): Result<T> { const data: any = [ {id: 1, name: '类型注解'}, {id: 2, name: '类型推论'}, {id: 3, name: '编译型语言'} ]; return {data}; } // 调用 this.features = getData<Feature[]>().data;

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

function getData<T>(): Promise<Result<T>> { const data: any = [ {id: 1, name: '类型注解'}, {id: 2, name: '类型推论'}, {id: 3, name: '编译型语言'} ]; return Promise.resolve<Result<T>>({data}); } // 调用 async 方式 async mounted () { this.features = (await getData<Feature[]>()).data; } // 调用 then 方式 mouted () { getData<Feature[]>().then((res: Result<Feature[]>) => { this.features = res.data; }) }

装饰器

装饰器用于扩展类或者它的属性和方法。

属性声明:@Prop

除了在 @Component 中声明,还可以采用@Prop的方式声明组件属性

export default class Demo extends Vue { // Props() 参数是为 vue 提供属性选项 // !称为明确赋值断言,它是提供给ts的 @Prop({type: String, require: true}) private msg!: string; }

事件处理:@Emit

// 通知父类新增事件,若未指定事件名则函数名作为事件名(驼峰变中划线分隔) @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;// 若有返回值则返回值作为事件参数 }

template 模板组件上正常写,@add-feature

变更监测:@Watch

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

装饰器原理

装饰器本质是工厂函数,修改传入的类、方法、属性等

类装饰器

// 类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数。 function log(target: Function) { // target是构造函数 console.log(target === Foo); // true target.prototype.log = function() { console.log(this.bar); } // 如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。 } @log class Foo { bar = 'bar' } const foo = new Foo(); // @ts-ignore foo.log();

实战一下 Component,新建 Decor.vue

<template> <div>{{msg}}</div> </template> <script lang='ts'> import { Vue } from "vue-property-decorator"; function Component(options: any) { return function(target: any) { return Vue.extend(options); }; } @Component({ props: { msg: { type: String, default: "" } } }) export default class Decor extends Vue {} </script>

源码简单了解

类装饰器主要依赖库:vue-class-component,深入源码,了解其背后究竟做了什么。

vue-property-decorator.js

import Vue from 'vue'; import Component, { createDecorator, mixins } from 'vue-class-component'; export { Component, Vue, mixins as Mixins };

createDecorator、applyMetadata 是核心,后续实现都依赖它,比如 Prop、Watch、Ref。

Prop 源码实现:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/d2f63218502d4d98cf08c3ff490cfda4.html