vue2使用ts vue-class-component的过程
作者:奥特曼
目前,对于Vue3来说,TypeScript的支持已经相当成熟,但公司的老项目一直处于迭代和维护无法从v2重构成v3,并且重构的成本也是很大的一个问题,所以记录一下vue2如何去搭配TypeScript。
一、脚手架创建项目
通过vue-cli进行安装
vue create v2ts
以下是脚手架的配置,仅供参考
二、vue-property-decorator
vue-property-decorator
是一个 Vue.js 的装饰器库,它提供了一些装饰器来让你在 Vue 组件中定义属性、计算属性、方法、事件等。使用这些装饰器可以让 Vue 组件的代码更加清晰简洁,同时也提高了代码的可读性和可维护性。
tip:引入Component是将类组件转换成Vue组件。
<script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component export default class HomeView extends Vue { } </script>
(1)变量
由于使用的class-component,所以定义变量也是比较简单,只需要把变量写在class里,使用private和public可以更好的区分私有还是共有。
<template> <div id="app"> {{ a }} {{ b }} </div> </template> <script lang="ts"> import { Vue } from 'vue-property-decorator' export default class HomeView extends Vue { private a = 1 public b = 2 } </script>
tip:注意 不要初始化不赋值或赋值为undefined,否则会识别不到这个变量,如果你只想定义这个变量也可以采取data函数的形式。
<script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component export default class HomeView extends Vue { data () { return { d: undefined } } }
(2)方法
<script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component export default class HomeView extends Vue { private a = 1 private add () { console.log(this.a) this.a++ } } </script>
(3) watch
语法:
@Watch('监听属性', { immediate, deep }) private 方法名 (新值,旧值) { console.log(v) }
示例:
<template> <div id="app"> {{ obj.a }} <button @click="add">+1</button> </div> </template> <script lang="ts"> import { Component, Vue, Watch } from 'vue-property-decorator' @Component export default class HomeView extends Vue { private obj = { a: 1 }; private add () { this.obj.a++ } @Watch('obj', { immediate: true, deep: true }) private updateA (v: { a: number }) { console.log(v) } } </script>
(4)计算属性
计算属性 在方法名前 加一个get就好了
<template> <div id="app"> {{ obj.a }} <button @click="add">+1</button> {{ doubleA }} </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component export default class HomeView extends Vue { private obj = { a: 1 }; private add () { this.obj.a++ } get doubleA () { return this.obj.a * 2 } } </script>
(5)生命周期
和之前区别不大 使用对应的函数名称
<script lang="ts"> @Component export default class HomeView extends Vue { created () { console.log(123) } mounted () { console.log(456) } } </script>
(6) 组件
(1)注册组件
<Son text="哈哈" />
(2) 父传子
父
<Son text="哈哈" />
子
<template> <div>{{ text }}</div> </template> <script lang="ts"> import { Component, Vue, Prop } from 'vue-property-decorator' @Component export default class Son extends Vue { @Prop({ type: String, default: '' }) text!:string } </script>
(3)子传父
子
<template> <div> <button @click="emit">子传父</button> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component export default class Son extends Vue { emit () { this.$emit('update', 123) } } </script>
父
<template> <div id="app"> <Son @update="updateHandler"/> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator' import Son from '@/components/Son.vue' @Component({ components: { Son } }) export default class HomeView extends Vue { updateHandler (val:number) { console.log(val, '接受了') } } </script>
也可以通过vue-property-decorator的形式 导出Emit 调用emit的方法即可
<template> <div class="hello"> <button @click="send">传值</button> </div> </template> <script lang="ts"> import { Component, Vue, Emit } from 'vue-property-decorator' @Component export default class HelloWorld extends Vue { @Emit() send ():number { return 20 } } </script>
(7)ref引用
<template> <div id="app"> {{ a }} <Son ref="son" /> </div> </template> <script lang="ts"> import Son from '@/components/Son.vue' import { Component, Vue } from 'vue-property-decorator' interface SonComponent extends Vue { logHello: ()=>void } @Component({ components: { Son } }) export default class App extends Vue { a = 1; mounted () { (this.$refs.son as SonComponent).logHello() } } </script>
三、vuex-class
为了更好的搭配vue-class-component 在使用vuex的时候可以安装 vuex-class 插件 帮助我们更好的使用装饰器开发
npm i vuex-class
(1)全局使用
store.ts
import Vue from 'vue' import Vuex, { Commit } from 'vuex' Vue.use(Vuex) interface state { username: string } export default new Vuex.Store({ state: { username: 'default' }, getters: { getUserName (state: state) { return '姓名' + state.username } }, mutations: { SET_USERNAME (state: state, val: string) { state.username = val } }, actions: { async requestUserName (context: { commit: Commit }, id: number) { const users = [ { id: 1, name: 'Ulrtraman' }, { id: 2, name: 'Monsters' } ] return new Promise((resolve) => { setTimeout(() => { const username = users.find(it => it.id === id)?.name context.commit('SET_USERNAME', username) resolve(username) }, 1000); }) } }, modules: { } })
组件调用:
<script lang="ts"> import { Component, Vue } from "vue-property-decorator"; import { State, Mutation, Action, Getter } from "vuex-class"; @Component export default class Sister extends Vue { @State("username") private username!:string; @Mutation("SET_USERNAME") private setUserName!:(name:string) => void @Action("requestUserName") private requestUserName!:(id:number) => void @Getter("getUserName") private getUserName!:string async created () { // 获取state的username console.log(this.username); // 调用mutation的方法 this.setUserName('abcd') // 调用actions的方法 this.requestUserName(2) // 获取getter console.log(this.getUserName); } } </script>
四个模块的导入使用大致相同
@模块("模块的属性命名") private 新名字!:类型;
(2)模块化
在开发中模块vuex的场景还是比较多的 达到 清晰 易维护。
store/user/user.ts
import { Commit } from 'vuex'; interface state { username: string } const state: state = { username: 'default' } const mutations = { SET_USERNAME (state: state, val: string) { state.username = val } } const getters = { getUserName (state: state) { return '姓名' + state.username } } const actions = { async requestUserName (context: { commit: Commit }, id: number) { const users = [ { id: 1, name: 'Ulrtraman' }, { id: 2, name: 'Monsters' } ] return new Promise((resolve) => { setTimeout(() => { const username = users.find(it => it.id === id)?.name context.commit('SET_USERNAME', username) resolve(username) }, 1000); }) } } export default { state, getters, mutations, actions, namespaced: true }
tip: 要加namespace 命名空间
store/index.ts
import Vue from 'vue' import Vuex from 'vuex' import user from './user/user' Vue.use(Vuex) export default new Vuex.Store({ modules: { user } })
组件调用:
<script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; import { namespace } from 'vuex-class'; const user = namespace('user'); @Component({ components: { Son, Sister } }) export default class App extends Vue { @user.State private username!: number; @user.Mutation private SET_USERNAME!: (name:string) => void; @user.Action private requestUserName!: (id:number) => void; @user.Getter private getUserName!: number; async beforeMount () { // state console.log('state:', this.username); // getter console.log('getter:', this.getUserName); // mutation this.SET_USERNAME('helloworld') // action await this.requestUserName(1); } } </script>
使用方法:
import { namespace } from 'vuex-class'; const 变量 = namespace('文件名'); .. @变量.模块 private 新名字!: 类型;
四、mixin
src/mixins/mixin.ts
import { Component, Vue } from 'vue-property-decorator' @Component export default class HelloWorld extends Vue { created () { console.log('mixin的created'); } }
使用mixin
<script lang="ts"> import { Component, Mixins } from 'vue-property-decorator' import mixin from '@/mixins/mixin' @Component export default class HelloWorld extends Mixins(mixin) { } </script>
到此这篇关于vue2使用ts vue-class-component的文章就介绍到这了,更多相关vue ts vue-class-component使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!