在Vue2项目中使用TypeScript
· 预计阅读时间:5 分钟
Tags:Vue2TypeScript
note
在Vue2项目中使用TypeScript,相关配置和语法
#
1、Vue2.x使用TypeScript#
1.1、安装依赖npm i typescript ts-loader vue-class-component vue-property-decorator vuex-class
ts-loader
和typescript
使用typescript必须的#
(1) vue-class-component
可以把组件写成 class 的模式,自定义装饰器,路由钩子#
(2) vue-property-decorator
提供这些装饰器#
(3) @Prop@PropSync@Model@ModelSync@Watch@Provide@Inject@ProvideReactive@InjectReactive@Emit@Ref@VModel@Component //由 vue-class-component 提供Mixins //由 vue-class-component 提供
vue-class-component和vue-property-decorator区别
import Component from 'vue-class-component';import { Component } from 'vue-property-decorator'
这里的 vue-property-decorator 此库完全依赖于 vue-class-component,所以都有 Component
vuex-class
提供class组件的VueX的支持#
(4) #
2、用ts实现的组件中使用VueX#
2.1、创建VueX文件@/store/index.ts
import Vue from "vue";import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({ state: { foo:"" }, getters: { foo: state => { return state.foo+"你好" } } mutations: { foo(state,value){ state.foo=value } }, actions: { foo(context,value){ setTimeout(() => { commit('foo',value) }, 1000) } }, modules: {},});
#
2.2、ts组件中使用VueXimport { Component, Ref, Vue } from "vue-property-decorator";import { State, Getter, Action, Mutation, namespace} from 'vuex-class' const someModule = namespace('path/to/module') @Componentexport class MyComp extends Vue { @State('foo') stateFoo @State(state => state.bar) stateBar @Getter('foo') getterFoo @Action('foo') actionFoo @Mutation('foo') mutationFoo @someModule.Getter('foo') moduleGetterFoo // If the argument is omitted, use the property name //如果省略参数,请使用属性名称 // for each state/getter/action/mutation type //对于每个状态/getter/action/mutation类型 @State foo @Getter bar @Action baz @Mutation qux created () { this.stateFoo // -> store.state.foo this.stateBar // -> store.state.bar this.getterFoo // -> store.getters.foo this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true }) this.mutationFoo({ value: true }) // -> store.commit('foo', { value: true }) this.moduleGetterFoo // -> store.getters['path/to/module/foo'] }}
#
3、使用ts实现组件的装饰器用法#
3.1、@Component- @Component(options) 的options 是配置 decorator 库不支持的属性, 如:name, components, filters, directives等
<template> <div id="app"> </div></template>
<script lang="ts">import { Component, Vue } from 'vue-property-decorator';
import test from './components/test.vue'
@Component({ name:"", components: { test, },})export default class Demo extends Vue { }</script>
import { Component, Vue } from "vue-property-decorator";@Componentexport default class Home extends Vue {}
#
3.2、data- data的的数据可以直接写在类中
import { Vue, Component, Prop } from 'vue-property-decorator' @Componentexport default class Demo extends Vue { //public(公共的任何地方被访问到,默认所有的属性和方法都是 public) //private (私有的,不能在声明它的类的外部访问,子类中也不允许被访问的) //protected (受保护的,它和 private 类似,区别是它在子类中是允许被访问的) public isDone: boolean = false; private decLiteral: number = 6; protected name: string = "bob"; //不写访问修饰符默认是public修饰符 list1: number[] = [1, 2, 3]; list2: Array<number> = [1, 2, 3]; //类型推断(不写明类型时会自动根据赋值推断类型) isDone = false; decLiteral = 6; name = "bob"; list1:= [1, 2, 3]; zoo= {};}
#
3.3、method- 直接写方法名,有返回数据写返回数据类型,有参数写参数类型
import { Vue, Component } from 'vue-property-decorator' @Componentexport default class Demo extends Vue { blindBoxItems1(){
} blindBoxItems2():String {
} blindBoxItems3(item:any):String {
}}
#
3.4、计算属性- 计算属性方法,在方法前加get关键字表示,其余和method是一样的
import { Vue, Component } from 'vue-property-decorator' @Componentexport default class Demo extends Vue { get blindBoxItems1():String {
} get blindBoxItems2(item:any):String {
}}
#
3.5、生命周期函数- 和method是一样的直接写在类中
import { Vue, Component } from 'vue-property-decorator' @Componentexport default class Demo extends Vue { created(){
} mounted(){
}}
#
3.6、@Propimport { Vue, Component, Prop } from 'vue-property-decorator' @Componentexport default class YourComponent extends Vue { @Prop(Number) readonly propA: number | undefined @Prop({ default: 'default value' }) readonly propB!: string @Prop({ type: String, default: 'default value' }) readonly propC!: string @Prop([String, Boolean]) readonly propD: string | boolean | undefined //断言是number @Prop() age!: number}
#
3.7、@PropSync- 可实现Prop双向绑定
import { Vue, Component, PropSync } from 'vue-property-decorator' @Componentexport default class YourComponent extends Vue { @PropSync('name', { type: String }) syncedName!: string}
原始非ts组件写法
export default { props: { name: { type: String, }, }, computed: { syncedName: { get() { return this.name }, set(value) { this.$emit('update:name', value) }, }, },}
#
3.8、@Watchimport { Vue, Component, Watch } from 'vue-property-decorator' @Componentexport default class YourComponent extends Vue { //当child改变时会自动调用onChildChanged方法 @Watch('child') onChildChanged(val: string, oldVal: string) {}
//当person改变时会自动调用onChildChanged方法和onPersonChanged2方法(监听到一个改变执行两个不同的方法) @Watch('person', { immediate: true, deep: true }) onPersonChanged1(val: Person, oldVal: Person) {} @Watch('person') onPersonChanged2(val: Person, oldVal: Person) {}}
原始非ts写法
export default { watch: { child: [ { handler: 'onChildChanged', immediate: false, deep: false, }, ], person: [ { handler: 'onPersonChanged1', immediate: true, deep: true, }, { handler: 'onPersonChanged2', immediate: false, deep: false, }, ], }, methods: { onChildChanged(val, oldVal) {}, onPersonChanged1(val, oldVal) {}, onPersonChanged2(val, oldVal) {}, },}
#
3.9、@Emit@Emit装饰器接收一个可选参数,作为事件名;如果没有提供这个参数,$emit会将回调函数的camelCase(驼峰式)转为kebab-case(短横线命名),并将其作为事件名;父组件中使用时监听该事件名即可
@Emit会将回调函数的返回值作为第二个参数,如果返回值是一个Promise对象,$emit会将Promise对象状态为resolved之后触发;
@Emit的回调函数的参数,会放在其返回值之后,一起被$emit当作参数使用;
import { Vue, Component, Emit } from 'vue-property-decorator' @Componentexport default class YourComponent extends Vue { count = 0 @Emit() addToCount(n: number) { this.count += n } @Emit('reset') resetCount() { this.count = 0 } @Emit() returnValue() { return 10 } @Emit() onInputChange(e) { return e.target.value } @Emit() promise() { return new Promise((resolve) => { setTimeout(() => { resolve(20) }, 0) }) }}
#
3.10、@Refimport { Vue, Component, Emit } from 'vue-property-decorator'@Componentexport default class YourComponent extends Vue { @Ref("blind_box") readonly blind_box!: HTMLButtonElement; getBlindBox() { this.blind_box.style.width = this.width + "px"; this.blind_box.style.height = this.height + "px"; }}