尝试用TypeScript写一个Vue-todo

TS看起来是大势所趋,据说vue3.0的源码都是用TS写的了,无论如何都应该学习一番TS了!

在实践中学习也不失为一种学习方式!

1. 学习之前无论如何也要先看看TypeSCript中文网

2. vue-cli 3.0 提供了开箱即用的TS环境,那就直接开始!

vue create vue-todo

3. three days later

4. 基本完成了

成果

尝试用TypeScript写一个Vue-todo

代码样子大概是这样,和JS写出来的差别还是很大的

<template>
  <div class="today">
    <div class="menu" v-if="todayTodos.length !== 0 || menuIndex !== 0">
      <template v-for="(menu, index) in menus">
        <div @click="filterTodos(index)" :key="index" :class="['item', `${menuIndex === index ? 'active' : ''}`]">{{menu}}</div>
      </template>
    </div>
    <transition
        enter-active-class="animated fadeInLeft"
        leave-active-class="animated fadeOutRight"
        mode="out-in"
        >
      <Todos
        :key="menuIndex"
        :todos="todayTodos"
        :emptyMsg="emptyMsg"
        :type="menuIndex"
      />
    </transition>
  </div>
</template>
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator'
import {Action, State, Getter} from 'vuex-class'
import Todos from '../components/Todos.vue'
@Component({
  components: {
    Todos,
  },
})
export default class Today extends Vue {
  // vuex-class 代替 mapAction 等帮助函数
  @State public todayTodos: any
  // @Action public getTodayTodos: any
  @Action public filterTodayTodos: any
  // TS data 不再需要 data () { return {}}
  public menus: string[] = ['全部', '已完成', '未完成']
  public menuIndex: number = 0
  // TS computed xuyao 需要关键字get
  // get Name() {return .....}
  public get emptyMsg(): string {
    if (this.menuIndex === 0) {
      return '这下你高兴了!今天居然无事可做!!!'
    } else if (this.menuIndex === 1) {
      return '你今天居然什么事都没做完!'
    } else {
      return '人生就该勤奋做事!!'
    }
  }
  // TS methods 不用写 methods: {}
  public async filterTodos(index: number): Promise<void> {
    if (index === 1) {
      await this.filterTodayTodos(true)
      this.menuIndex = index
    } else if (index === 2) {
      await this.filterTodayTodos(false)
      this.menuIndex = index
    } else {
      await this.filterTodayTodos()
      this.menuIndex = index
    }
  }
  // TS 生命周期函数,和原来一样的写法
  public created(): void {
    this.filterTodayTodos()
  }
}
</script>
<style lang="less" scoped>
@import '../common/main';
.today {
  .menu {
    display: flex;
    width: 100%;
    height: 12vh;
    background: @mainColor;
    .item {
      flex: 1;
      height: 12vh;
      line-height: 12vh;
      font-size: 1.2rem;
      box-sizing: border-box;
      color: rgb(178, 185, 190);
      // &:active {
      //   border-bottom: 3px solid #234; 
      // }
    }
    .active {
      border-bottom: 3px solid rgb(78, 54, 54);
      color: rgb(255, 255, 255);
    }
  }
}
</style>

5. 总结

1 这次实践离真正熟练还差得很遥远,但至少对强类型是有所理解了,也能感觉到TS的优势,至少代码提示比JS好太多了!
2 也遇见比较多的不适应

比如写这个notify组件

notify.js

import Vue from 'vue'
import Notification from './Notify.vue'

// const NotificationConstructor = Vue.extend(Notification)
const notify = (options) => {
  if (Vue.prototype.$isServer) {
    return
  }
  const instance = new Notification({
    propsData: options,
  })
  instance.$mount()
  document.body.appendChild(instance.$el)
  // console.log(instance)
  return instance
}
export default notify
如果我这里用TS,改为 notify.ts,用ts的写法。
执行 notify(options) 一定是报错的,无奈只能用js的写法,然后你用了JS,你又不得不写个notify.d.ts来声明这个东东。
至于错误原因留待自己的技术进步吧!

然后是这个 vue-chartjs

用TS的写法也是不成功的,这个只能求助大佬了

JS写法,完全没问题

<script>
import { Line, Bar, PolarArea, Radar, Doughnut, Pie } from 'vue-chartjs'

export default {
  extends: Line,
  props: {
    chartdata: {
      type: Object,
      default: null,
    },
    options: {
      type: Object,
      default: null,
    },
  },
  mounted() {
    this.renderChart(this.chartdata, this.options)
  },
}
</script>

TS写法,我也不知道错在何处

<script lang="ts">
import { Line, Bar } from 'vue-chartjs'
import {Prop, Component, Vue} from 'vue-property-decorator'
@Component
export default class BarChart extends Bar {
  @Prop({default: null}) public chartdata!: any
  @Prop({default: null}) public options!: any
  public mounted() {
    this.renderChart(this.chartdata, this.options)
  }
}
</script>

最后github地址

相关推荐