TS 在vue中使用的正确方式,vue-property-decorator
为什么要使用TS?TS 能带来什么好处?
- TypeScript 使得抽象清晰可见;
- TypeScript 使代码更容易阅读和理解;
- TypeScript的设计目的应该是解决JavaScript的“痛点”:弱类型和没有命名空间,导致很难模块化,不适合开发大型程序。另外它还提供了一些语法糖来帮助大家更方便地实践面向对象的编程。
是的 这样并不直观,我用一个例子来说明我的意思。让我们来看看这个函数ajax()。我们能从中得到什么信息
ajax(url, options)
我们唯一能确定的是这个函数有两个参数。我们可以猜测这些类型。也许第一个是字符串,第二个是配置对象。但这只是猜测,我们可能错了。我们不知道什么选项进入设置对象(它们的名称和类型),或者该函数返回什么
以下是一个类型版本:
interface IAjaxOptions {
asyns?: boolean,
contentType?: any,
methods?: string
// ...
}
interface IAjaxJSON {
resJSON?: any
// ...
}
ajax(url: string, options: IAjaxOptions): IAjaxJSON
它给了我们更多的信息
- 这个函数的第一个参数是一个字符串。
- 设置参数是可选的。我们可以看到所有可以传递到函数中的选项,不仅是它们的名称,还包括它们的类型。
- 函数返回一个IAjaxJSON对象,我们可以看到它的属性和函数。
对TypeScript不熟悉的同学,可以移步TypeScript官网
在vue中使用TS
基于vue cli安装TS,以下几个文件 与之前有些不同:
- tsconfig.json: typescript配置文件,主要用于指定待编译的文件和定义编译选项
- shims-tsx.d.ts: 允许.tsx 结尾的文件,在 Vue 项目中编写 jsx 代码
- shims-vue.d.ts: 主要用于 TypeScript 识别.vue 文件,Ts 默认并不支持导入 vue 文件
在使用过程中可能会碰的一些问题
https://blog.csdn.net/weixin_41294480/article/details/114581229
装饰器 vue-property-decorator
这个组件完全依赖于vue-class-component.它具备以下几个属性:
- @Component (完全继承于vue-class-component)
- @Emit
- @Inject
- @Provice
- @Prop
- @Watch
- @Model
- Mixins (在vue-class-component中定义);
安装
npm install vue-property-decorator
或
yarn add vue-property-decorator
使用
当我们在vue单文件中使用TypeScript时,引入vue-property-decorator之后,script中的标签就变为这样:
@Component
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
import Hello from './Hello.vue'
@Component({
name: 'name',
components: { Hello }
})
export default class "组件名" extends Vue{}
</script>
等同于
<script>
import Vue from 'vue';
import Hello from './Hello.vue'
export default {
name: 'name',
components: {
Hello
}
}
</script>
@Prop
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
@Component
export default class "组件名" extends Vue{
@Prop({
type: String,
default: 'prop'
}) private msg?: string;
@Prop({
default: 0,
required: true
}) private total!: number;
}
</script>
等同于
// ? 表示可选
// ! 表示一定有值
<script>
import Vue from 'vue';
export default {
props: {
msg: {
type: String,
default: 'prop'
},
total: {
type: Number,
required: true,
default: 0
}
}
}
</script>
计算属性 computed、data数据
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
@Component
export default class "组件名" extends Vue{
// ------------- 变量 data
private num: number = 20
// ------------- 计算属性 computed allnum 是计算后的值
get allnum (): number {
return this.num + 10
}
}
</script>
@Watch
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
@Component
export default class "组件名" extends Vue{
// ------------- 变量 data
private num: number = 20
// ------------- 监听 watch
@Watch('num', { deep: true })
private onChangeNum (newValue: number, oldValue: number) {
console.log(`watch: newValue: ${newValue}; oldValue: ${oldValue}`)
}
}
</script>
methods、生命周期
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
@Component
export default class "组件名" extends Vue{
// ------------- 变量 data
private num: number = 20
// ------------ 生命周期
private created () {
console.log('created:', this.num)
}
private mounted () {
console.log('mounted:', this.num)
}
// ----------- 方法 methods void 表示该函数无返回值
private upNumber () {
this.num += 2
}
private downNumber (): void {
this.num -= 2
}
}
</script>
@Emit 事件
Child.vue
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<a-button @click="backParent">子组件</a-button>
</div>
</template>
<script lang="ts">
import { Vue, Emit, Component } from 'vue-property-decorator'
@Component
export default class Home extends Vue {
// 写法一 emit()括号里不写函数名 函数名为驼峰 在父组件接收函数要采用(驼峰式会转为横杠式写法) return-parent
// @Emit()
// private returnParent (): object {
// return { msg: '我是子组件返回的对象' }
// }
// 写法二: 注意,这时父组件接收值时是用@Emit("returnParent")括号中的returnParent接收的,returnParent会把正面的方法名字覆盖。
// (treturnParent)是自定义的 在父组件接收函数要采用 returnParent驼峰
@Emit('returnParent')
private backParent (): object {
return { msg: '我是子组件返回的对象' }
}
}
</script>
Parent.vue
<template>
<Home @returnParent="handlerChildValue"/>
<!-- <Home @return-parent="handlerChildValue"/> -->
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
@Component
export default class Home extends Vue {
// Emit
private handlerChildValue (obj: object) {
console.log(obj)
}
}
</script>
vuex
它具备以下几个属性
- VuexModule
export default class TestModule extends VuexModule { }
VuexModule 提供了一些基本属性,包括 namespaced,state,getters,modules,mutations,actions,context - @Mutation
- @Action
- getModule
得到一个类型安全的 store,module 必须提供 name 属性 - @Module
@Module 标记当前为 module @Module({ dynamic: true, store, name: “user” })- class User extends VuexModule implements IUserState { }
- module 本身有几种可以配置的属性:
namespaced:boolean 启/停用 分模块
stateFactory:boolean 状态工厂 - dynamic:boolean 在 store 创建之后,再添加到 store 中。开启 dynamic 之后必须提供name属性
- 指定模块名称store:Vuex.Store 实体 提供初始的 store
安装
npm install vuex-module-decorators
或
yarn add vuex-module-decorators
传统的 store 用法
export default {
namespaced:true,
state:{
name:""
},
getters:{
getName(state){ return state.name}
},
mutations:{
setNameSync(state,payload){
state.name = payload
}
},
actions:{
setFoo({commit},payload){
commot("setNameSync",payload)
}
}
}
使用vuex-module-decorators装饰器
import { VuexModule, Mutation, Action, getModule, Module } from 'vuex-module-decorators'
export interface IUserState {
name: string
}
import store from '@/store/index'
@Module({ namespaced: true, dynamic: true, name: 'user', store })
class User extends VuexModule implements IUserState {
public name = ''
@Mutation
public SET_INFO (name: IuserInfo) {
this.name = name
}
@Action
public loginAction (params: any) {
return new Promise((resolve, reject) => {
login(params).then(res => {
console.log('成功')
this.SET_INFO(res.user.name)
resolve(res)
}).catch(err => {
console.log(err)
reject(err)
})
})
}
}
export const UserModule = getModule(User)
示例
基于 TS+Vue+Ant Design of Vue 构建了一个简单的中后台通用模板
功能如下:
- 登录 / 注销
- 权限验证
- 页面权限
- 权限配置
- 多环境发布
- Dev / Test / Prod
- 全局功能
- 动态侧边栏(支持多级路由嵌套)
- Mock 数据 / Mock 服务器
- 引导页
- 错误页面
- 404
vuex tsx
里面对于在 vue 中使用 typescript 的各种场景都有很好的实践,大家感兴趣的可以参考一下
如要使用,更多功能大家可自行完善
https://github.com/ZhangKKKK/ts-vue-antdv