项目配置在此不再做说明,本文是为了让新手更快熟悉ts在vue2.x中的使用。

以下默认读者已掌握vue的基础开发。

一、vue模板设置

在改造.vue文件前,我们需要安装一个插件vue-property-decorator

为了让webpack把script内的代码识别为ts,除了需要改造一下script标签内的内容,其他地方都无需修改

<script lang="ts">
</script>复制代码

二、常用装饰器的使用

装饰器用于扩展类或者它的属性和方法。@xxx就是装饰器的写法

常见的有@Prop,@Emit,@Watch等等

<script lang="ts">
import { Component, Vue, Watch  } from 'vue-property-decorator';
@Component()
export default class Home extends Vue {
    // data中的参数   
    private str: boolean = 'aaa';  
        //  Watch --> 监听
    @Watch('config')  
    onConfigChange(val: any, oldVal: any) {    
    }
 
  //  生命周期直接用同名方法即可,mounted同理
    private created(){
        this.init();
    }
 
  // 方法 --> 相当于methods中的方法
    private init(){
        console.log('init');
    }
        // 访问器当做计算属性 --> 相当于computed
        //computed: {
    //  count() { 
    //    return this.str.length
    //  }
    //}
    get count() {
      return this.str.length
    }
}
</script>复制代码

三、组件引入方式

在导入vue文件的时候,要写上.vue后缀,因为TypeScript默认识别ts文件

<script lang="ts">
    import Test from './test.vue'; // 引入Test组件
    import { Component, Prop, Vue, Watch  } from 'vue-property-decorator';
    
  @Component({    
      components: {      
          Test    
      }
  })
    export default class Home extends Vue {
    // xxx
  }
</script>复制代码

四、父子组件通信

众所周知,父 -> 子 传值,子组件通过props接收参数, 子 -> 父组件 通过emit 传值

在ts中如下:

子组件HelloWorld

<template>
  <div>
    <h1>HelloWorld 组件</h1>
    <div>父组件传值{{ msg }}</div>
    <el-button @click="onClick">点我向父组件传值</el-button>
  </div>
</template>

<script lang="ts">
import { Component, Emit, Prop, Vue } from 'vue-property-decorator'

@Component
export default class HelloWorld extends Vue {
  // 括号中的是传给vue的配置
  // ts特性展示,!是赋值断言,表示该属性一定会被赋值,编译器不用警告
  @Prop({ type: String, required: true }) private msg!: string

  clickCount: number = 0 // ts自带类型推断,也可写为 clickCount = 0

  @Emit()  // 回调函数直接声明即可
    // 或 @Emit('on-click') 
  onClick() {
    this.clickCount += 1
    return this.clickCount
  }
}
</script>复制代码

父组件Home

<template>
  <div class="home">
    <el-input v-model="msg"></el-input>
        // 传值与js版本无异
    <HelloWorld :msg="msg" @on-click="onChildClick" />
  </div>
</template>

<script lang="ts">
import { Vue, Component, Watch } from 'vue-property-decorator'
import HelloWorld from '@/components/HelloWorld.vue'
@Component({
  components: {
    HelloWorld,
  },
})
export default class Home extends Vue {
  // data
  msg = 'aaa'
  onChildClick(e: number) {
    console.log('child:', e)
  }
}
</script>复制代码

五、状态管理

在js版本中,我们一般使用vuex来做状态管理,ts中,我们可用`vuex-module-decorators`做状态管理

import { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-decorators'
import store from './index'
// 动态注册模块设置,跟js类似
@Module({ store: store, name: 'counter', namespaced: true }) 
class CounterModule extends VuexModule {
    count = 1
  @Mutation
  add() {
    // 通过this直接访问count
    this.count++
  }
// 定义getters
    get doubleCount() {
    return this.count * 2;
  }
  @Action
  asyncAdd() {
        setTimeout(() => {
            // 通过this直接访问add this.add()
        }, 1000);
 
    }
}
// 导出模块应该是getModule的结果
export default getModule(CounterModule)


// 在组件中使用
<template>
  <p @click="add">{{$store.state.counter.count}}</p>
    <p @click="asyncAdd">{{count}}</p>
</template>

<script lang="ts">
  import CounterModule from '@/store/counter'
  @Component
  export default class Home extends Vue {
    get count() {
      return CounterModule.count
    }
    add() { // 相当于js版本中 this.$store.commit('count/add')
      CounterModule.add()
    }
    asyncAdd() { // 相当于js版本中 this.$store.dispatch('count/add')
      CounterModule.asyncAdd()
    } 
  }
</script>复制代码