VUE中应用TypeScript(上)

Posted 前端菜鸟逆袭架构师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VUE中应用TypeScript(上)相关的知识,希望对你有一定的参考价值。

资源

1. TypeScript参考:http://www.typescriptlang.org
2. Vue+TypeScript:https://cn.vuejs.org/v2/guide/typescript.html


知识点


1. ts核心语法
2. ts+vue
3.
装饰器应用
4. 装饰器原理
5. vue-property-decorator源码解析

准备工作

新建一个基于tsvue项目

VUE中应用TypeScript(上)


在已存在项目中安装typescript

命令:vue add @vue/typescript

VUE中应用TypeScript(上)

请暂时忽略引发的几处Error,它们不会影响项目运行,我们将在后面处理它们。

TS特点


类型注解、类型检测


接口
泛型
装饰器
类型声明

类型注解和编译时类型检查

使用类型注解约束变量类型,编译器可以做静态类型检查,使程序更加健壮

类型基础

main.js中引入:

VUE中应用TypeScript(上)

let var1: string; // 类型注解 var1 = "尤雨溪真帅"// 正确var1 = 4; // 错误// 编译器类型推断可省略这个语法 let var2 = true;var2 = 4; // 错误// 常见原始类型: string,number,boolean,undefined,null,symbol// 类型数组let arr: string[];arr = ['Tom']; // 或Array<string>// 任意类型any let varAny: any; varAny = 'xx'; varAny = 3;// any类型也可用于数组let arrAny: any[];arrAny = [1, true, "free"]; arrAny[1] = 100;// 函数中的类型约束function greet(person: string): string { return 'hello, ' + person;}// void类型,常用于没有返回值的函数 function warn(): void {}

范例,HelloWorld.vue

<template> <div> <ul> <li v-for="feature in features" :key="feature">{{feature}}</li> </ul> </div></template><script lang='ts'>import { Component, Prop, Vue } from "vue-property-decorator";//方式一:class-style(用的比较多)@Componentexport default class Hello extends Vue {  @Prop() private msg!:string;  //属性将成为data中数据 features: string[] = ["类型注解", "编译型语言"]; }//方式二:option-style(官方:该方式会稍微有点问题)import Vue form 'vue'export default Vue.extend({data(this)})//this出现导致ts编译无法知道一些动态属性,经常情况下this.$XX,导致很难推断</script>

VUE中应用TypeScript(上)

方式三:jsx方式

特点:上下文很清楚;代码提示很强,可以做类型检测

VUE中应用TypeScript(上)

    使用:

VUE中应用TypeScript(上)

类型别名

使用类型别名自定义类型

// 可以用下面这样方式定义对象类型const objType: { foo: string, bar: string }// 使用type定义类型别名,使用更便捷,还能复用 type Foobar = { foo: string, bar: string } const aliasType: Foobar

接口和类型别名是可以互换的,没有什么区别。对ide有影响,程序本身没影响。2.7版本之前不支持类型别名。对于通用性来讲,接口比别名更好一些。VUE中应用TypeScript(上)

范例:使用类型别名定义Featuretypes/index.ts

export type Feature = { id: number, name: string}

使用自定义类型,HelloWorld.vue

<template> <div><!--修改模板--> <li v-for="feature in features" :key="feature.id">{{feature.name}}</li> </div></template><script lang='ts'>// 导入接口import { Feature } from "@/types";@Componentexport default class Hello extends Vue {// 修改数据结构features: Feature[] = [{ id: 1, name: "类型注解" }]; }</script>

VUE中应用TypeScript(上)

联合类型

希望某个变量或参数的类型是多种类型其中之一
let union: string | number;union = '1'; // okunion = 1; // ok

使用:扩大范围:VUE中应用TypeScript(上)

交叉类型

想要定义某种由多种类型合并而成的类型使用交叉类型
type First = {first: number};type Second = {second: number};// FirstAndSecond将同时拥有属性first和second type FirstAndSecond = First & Second;

范例:利用交叉类型给Feature添加一个selected属性

// types/index.tsexport type Feature={ id:number; name:string;}type Select = { selected: boolean}export type FeatureSelect = Feature & Select

使用:VUE中应用TypeScript(上)

使用这个FeatureSelectHelloWorld.vue

features: FeatureSelect[] = [ { id: 1, name: "类型注解", selected: false },  { id: 2, name: "编译型语言", selected: true }];
<li :class="{selected: feature.selected}">{{feature.name}}</li>
.selected { background-color: rgb(168, 212, 247);}

函数


必填参:参数一旦声明,就要求传递,且类型需符合
function greeting(person: string): string { return "Hello, " + person;}greeting('tom')

可选参数:参数名后面加上问号,变成可选参数

function greeting(person: string, msg?: string): string { return "Hello, " + person;}

默认值(默认值与?可选冲突)默认值与可选参数放在必须参数后面

function greeting(person: string, msg = ''): string { return "Hello, " + person;}

*函数重载:以参数数量或类型区分多个同名函数,先声明,再实现。

// 重载1function watch(cb1: () => void): void;// 重载2function watch(cb1: () => void, cb2: (v1: any, v2: any) => void): void; // 实现function watch(cb1: () => void, cb2?: (v1: any, v2: any) => void) { if (cb1 && cb2) {  console.log('执行watch重载2'); } else {  console.log('执行watch重载1'); }}

范例:新增特性,Hello.vue

<div><input type="text" placeholder="输入新特性" @keyup.enter="addFeature"></div>
addFeature(e: KeyboardEvent) {//类型断言// e.target是EventTarget类型,需要断言为HTMLInputElement const inp = e.target as HTMLInputElement;const feature: FeatureSelect = { id: this.features.length + 1, name: inp.value, selected: false } this.features.push(feature); inp.value = "";}

范例:生命周期钩子,Hello.vue

created() { this.features = [{ id: 1, name: "类型注解" }];}

class的特性

ts中的类和es6中大体相同,这里重点关注ts带来的访问控制等特性

class Parent { private _foo = "foo"; // 私有属性,不能在类的外部访问  protected bar = "bar"; // 保护属性,可以在子类中访问 // 参数属性:构造函数参数加修饰符,能够定义为成员属性  constructor(public tua = "tua") {} // 方法也有修饰符 private someMethod() {} // 存取器:属性方式访问,可添加额外逻辑,控制读写性  get foo() { return this._foo; } set foo(val) { this._foo = val; }}

范例:利用getter设置计算属性,Hello.vue

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

接口

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

// Person接口定义了结构 interface Person { firstName: string; lastName: string;}// greeting函数通过Person接口约束参数解构 function greeting(person: Person) { return 'Hello, ' + person.firstName + ' ' + person.lastName;}greeting({firstName: 'Jane', lastName: 'User'}); // 正确 greeting({firstName: 'Jane'}); // 错误

范例:Feature也可用接口形式约束,./types/index.ts

// 接口中只需定义结构,不需要初始化 export interface Feature {id: number; name: string;}

Interface vs type aliases:https://www.typescriptlang.org/docs/handbook/advanced-types.html#interfaces-vs-type-aliases

恭喜你,今天又进步了一点点!

以上是关于VUE中应用TypeScript(上)的主要内容,如果未能解决你的问题,请参考以下文章

Vue JS typescript 组件找不到注入实例属性

Vue+Typescript中在Vue上挂载axios使用时报错

Vue + VueX + Typescript + Vue 路由器。组件未销毁

如何在 Vue 和 TypeScript 应用中正确的全局注册 axios

... Vue-TypeScript 应用程序中的 mapActions 导致错误

Vue 3系列之03——Vue 3使用TypeScript