范例指么,HelloWorld.vue
<template>
<div>
<!-- 新增 -->
<input type="text" @keyup.enter="addFeature" />
<div v-for="item in features" :key="item.id" :class="{selected: item.selected}">{{ item.name }}</div>
<div>{{count}}</div>
</div>
</template>
<script lang="ts">
// import { Vue } from "vue-property-decorator";
import { Vue, Component, Prop, Emit, Watch } from "vue-property-decorator";
import { FeatureSelect } from "@/types";
// 泛型方法
function getList<T>(): Promise<T> {
return Promise.resolve([
{ id: 1, name: "類(lèi)型注解", selected: false },
{ id: 2, name: "編譯型語(yǔ)言", selected: true }
] as any);
}
@Component
export default class HelloWorld extends Vue {
// 括號(hào)里面是傳給vue的配置
@Prop({type: String, required: true})
msg!: string;
// message = 'class based component'
// ts特性展示,!是賦值斷言桥氏,表示該屬性一定會(huì)被賦值,編譯器不用警告
features: FeatureSelect[] = [];
// 生命周期直接用同名方法即可
async created() {
// this.features = await getList<FeatureSelect[]>();
const resp = await this.$axios.get<FeatureSelect[]>('/api/list')
this.features = resp.data
}
@Watch('msg')
onMsgChange(val:string, old:string) {
console.log(val);
}
// 回調(diào)函數(shù)直接聲明即可
@Emit('add-feature')
addFeature(e: KeyboardEvent) {
// 斷言為Input,一般當(dāng)一些類(lèi)型需要變得更具體的時(shí)候需要使用as斷言
// 這里把EventTarget類(lèi)型斷言為它的子類(lèi)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 = "";
// 返回值作為事件參數(shù)
return feature
}
// 訪問(wèn)器當(dāng)做計(jì)算屬性
get count() {
return this.features.length;
}
}
</script>
<style scoped>
.selected {
background-color: rgb(205, 250, 242);
}
</style>
聲明文件
使用ts開(kāi)發(fā)時(shí)如果要使用第三方j(luò)s庫(kù)的同時(shí)還想利用ts諸如類(lèi)型檢查等特性就需要聲明文件惨奕,類(lèi)
似 xx.d.ts
同時(shí),vue項(xiàng)目中還可以在shims-vue.d.ts中對(duì)已存在模塊進(jìn)行補(bǔ)充
npm i @types/xxx
范例:利用模塊補(bǔ)充$axios屬性到Vue實(shí)例竭钝,從而在組件里面直接用
// main.ts
import axios from 'axios'
Vue.prototype.$axios = axios;
// shims-vue.d.ts
import Vue from "vue";
import { AxiosInstance } from "axios";
declare module "vue/types/vue" {
interface Vue {
$axios: AxiosInstance;
}
}
范例:給krouter/index.js編寫(xiě)聲明文件梨撞,index.d.ts
import VueRouter from "vue-router";
declare const router: VueRouter
export default router
裝飾器
裝飾器用于擴(kuò)展類(lèi)或者它的屬性和方法。@xxx就是裝飾器的寫(xiě)法
常見(jiàn)的有@Prop,@Emit,@Watch
具體使用見(jiàn)文章開(kāi)頭的例子
狀態(tài)管理推薦使用:vuex-module-decorators
vuex-module-decorators 通過(guò)裝飾器提供模塊化聲明vuex模塊的方法香罐,可以有效利用ts的類(lèi)型系
統(tǒng)卧波。
安裝
npm i vuex-module-decorators -D
根模塊清空,修改store/index.ts
export default new Vuex.Store({})
定義counter模塊庇茫,創(chuàng)建store/counter
import { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-
decorators'
import store from './index'
// 動(dòng)態(tài)注冊(cè)模塊
@Module({ dynamic: true, store: store, name: 'counter', namespaced: true }) class CounterModule extends VuexModule {
count = 1
@Mutation
add() {
// 通過(guò)this直接訪問(wèn)count
this.count++
}
// 定義getters
get doubleCount() {
return this.count * 2;
}
@Action
asyncAdd() {
setTimeout(() => {
// 通過(guò)this直接訪問(wèn)add this.add()
}, 1000);
} }
// 導(dǎo)出模塊應(yīng)該是getModule的結(jié)果
export default getModule(CounterModule)
使用港粱,App.vue
<p @click="add">{{$store.state.counter.count}}</p>
<p @click="asyncAdd">{{count}}</p>
import CounterModule from '@/store/counter'
@Component
export default class App extends Vue {
get count() {
return CounterModule.count
}
add() {
CounterModule.add()
}
asyncAdd() {
CounterModule.asyncAdd()
} }
裝飾器原理
裝飾器是工廠函數(shù),它能訪問(wèn)和修改裝飾目標(biāo)旦签。
類(lèi)裝飾器啥容,07-decorator.ts
//類(lèi)裝飾器表達(dá)式會(huì)在運(yùn)行時(shí)當(dāng)作函數(shù)被調(diào)用,類(lèi)的構(gòu)造函數(shù)作為其唯一的參數(shù)顷霹。 function log(target: Function) {
// target是構(gòu)造函數(shù)
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();
方法裝飾器
function rec(target: any, name: string, descriptor: any) { // 這里通過(guò)修改descriptor.value擴(kuò)展了bar方法
const baz = descriptor.value;
descriptor.value = function(val: string) {
console.log('run method', name);
baz.call(this, val);
}
}
class Foo {
@rec
setBar(val: string) {
this.bar = val
} }
foo.setBar('lalala')
屬性裝飾器
// 屬性裝飾器
function mua(target, name) {
target[name] = 'mua~~~'
}
class Foo {
@mua ns!:string;
}
console.log(foo.ns);
稍微改造一下使其可以接收參數(shù)
function mua(param:string) {
return function (target, name) {
target[name] = param
}
}