Vue中使用ts
typescript引入新建项目创建项目时,选择ts已存在项目vue add @vue/typescript项目内使用创建类型声明文件src/types/index.ts//类型声明export type Info = {id: numbername: string}//交叉类型export type Infolist = Info & {selected:boolean}//泛型expo
·
typescript引入
新建项目
创建项目时,选择ts
已存在项目
vue add @vue/typescript
项目内使用
状态管理
vuex-module-decorators通过装饰器提供模块化声明vuex模块的方法,可以有效利用ts的类型系统
安装
npm i vuex-module-decorators -D
vuex-module-decorators git地址
src/store/index.ts
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
export default new Vuex.Store({})
src/store/counter.ts
import {Module, VuexModule, Mutation, Action, getModule} from 'vuex-module-decorators'
import store from '@/store'
//动态注册模块
@Module({dynamic:true,store,name:'Counter',namespaced:true})
//es6定义类的方式
export default class Counter extends VuexModule{
count = 1
@Mutation
add(){
this.count++
}
//存取器,相当于getters
get doubleCount(){
return this.count*2
}
@Action
asyncAdd(){
setTimeout(()=>{
this.add()
},1000)
}
}
//导出模块应该是getModule的结果
export const CountModule = getModule(Counter)
main.ts中引入
import store from './store'
new Vue({
render: h => h(App),
store
}).$mount('#app')
创建类型声明文件
src/types/index.ts
//类型声明
export type Info = {
id: number
name: string
}
//交叉类型
export type Infolist = Info & {selected:boolean}
//泛型
export interface Result<T>{
code:number,
data:T
}
组件内部语法变更
父组件
<template>
<div class="hello">
<p>{{content}}</p>
<p @click="add">{{$store.state.Counter.count}}</p>
<p @click="asyncAdd">{{count}}</p>
<TsTest msg="hello typescript" @add-list="onClick"></TsTest>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import {CountModule} from '@/store/counter'
@Component({
components:{
//导入子组件需要加入./确定为当前目录,否则因为设置别名的原因会找不到文件
//懒加载导入组件
TsTest:()=>import('./tstest/index.vue')
}
})
export default class HelloWorld extends Vue {
//接收子组件传过来的值
content = "asd"
onClick(res:any){
this.content = res.name
}
//组件内使用vuex方法
get count(){
return CountModule.count
}
add(){
CountModule.add()
}
asyncAdd(){
CountModule.asyncAdd()
}
}
</script>
<style scoped>
</style>
子组件
<template>
<div>
<h2>{{msg}}</h2>
<p>{{foo}}</p>
<input type="text" @keydown.enter="addList">
<ul>
<li v-for="item in list" :key="item.id" :class="{selected:item.selected}">{{item.name}}</li>
</ul>
<p>总数{{count}}</p>
</div>
</template>
<script lang="ts">
import { Prop, Component, Vue, Emit, Watch } from 'vue-property-decorator';
//导入类型和接口
import {Infolist,Result} from '@/types'
//泛型方法
function getList<T>(): Promise<Result<T>>{
const data: any = [{
id:1,
name:"aaa",
selected: false
},{
id:2,
name:"bbb",
selected: true
}]
return Promise.resolve({
code:200,
data
})
}
@Component
export default class TsTestOne extends Vue {
//装饰器,内部可传参
@Prop()
msg!:string
//数据定义
foo = "foo"
list:Infolist[] = []
//生命周期
async created(){
this.list = (await getList<Infolist[]>()).data
}
mounted(){
this.foo = "welcome to 临涧村"
}
//事件
//向父组件传值
//装饰器中的参数为事件名,若为指定则函数名为事件名,父组件中需要以羊肉串命名方式去添加
@Emit()
addList(e: KeyboardEvent):Infolist{//若没有返回值,形参将作为事件参数
//类型断言
const inp = e.target as HTMLInputElement
const item: Infolist = {
id: this.list.length + 1,
name: inp.value,
selected: false
}
this.list.push(item)
inp.value = ""
return item;//存在返回值,返回值作为事件参数
}
//存取器作为计算属性
get count(){
return this.list.length
}
//watcher监听
@Watch("list")
onListChange(newVal:Infolist[],oldVal:Infolist[]){
console.log(newVal)
}
}
</script>
<style scoped>
.selected{
background: #ccc;
}
</style>
声明文件
要使用第三方js库,同时还想利用ts类型检查特性,就需要用到声明文件
类似xx.d.ts
如需要使用vue-router,就在router目录下新建index.d.ts
import VueRouter from 'vue-router'
declare const router: VueRouter
export default router
装饰器原理
常用装饰器用法
用于扩展类或者它的属性和方法
装饰器本质就是一个工厂函数,能访问或修改装饰目标
//类装饰器
//类装饰器表达式会在运行时当做函数被调用
//类的构造函数作为其唯一参数
function log(target:Function){
target.prototype.log = function(){
console.log(this.bar)
}
}
//方法装饰器
/*
descriptor为属性描述符
{
value: 属性值,
enumerable: false, // 是否可枚举
configurable: true, // 是否可配置
writable: true // 是否可写
}
*/
function rec(target:any,name:string,descriptor:any){
//通过修改descriptor.value扩展bar方法
const baz = descriptor.value;
descriptor.value = function(val:string){
console.log('run method',name)//run method setBar
baz.call(this,val)
}
}
//属性装饰器
function msg(target:any,name:string){
target[name] = "bbb"
}
@log
class Foo{
bar = 'bar'
@msg par!:string
@rec
setBar(val:string){
this.bar = val
}
}
const foo = new Foo()
foo.log()//bar
foo.setBar("aaa")
foo.log()//aaa
console.log(foo.par)//bbb
更多推荐
已为社区贡献11条内容
所有评论(0)