【Typescript】记录用TS重构Todolist的过程

在这里插入图片描述
在这里插入图片描述
有人说:用过ts的人的反应,只有真香和真tm香

Git

git clone https://github.com/DrBallon/TodoList.git --branch vue

搭建框架

因为暂时不擅长各种插件和配置,所以基础框架用vue-cli一梭子搞定

vue-cli 版本 4

vue create todolist-0.22
//1.Please pick a preset: Manually select features
选择"Manually select features" 手动选择要用的组件
//2.Check the features needed for your project: 
选择 "Typescript" "Vuex" "CSS-processors"(我用了sass)
//3.Choose a version of Vue.js that you want to start the project with
选择 vue 2.x
//4.Use class-style component syntax?
//选择是否使用基于类的 API
选择 y 确定
//5.Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)?
选择 y 确定

vuex

个人喜欢先从数据搞起,先重构vuex部分。

更改部分

//以下部分类似,仅仅需要设置参数的类型以及微调
index
mutations
state
//仅仅是导出字符串,只需要把文件后缀名修改
mutation_types
//actions 因为tytypescript开启严格模式对格式要求较高,此处改变较多
actions

//新增部分,保存与vuex相关的各种数据格式接口
IFs.ts

mutations

index,mutations,state类似,以mutations为例子

    //js写法
    getGroups(state) {},
    //给函数参数添加类型
    getGroups(state: State) {},
    
    //ps.State保存在IFs.ts里,通过import引入
    //mutations.ts
    import {State} from './IFs'
    
    //IFs.ts
    export interface State{
        ...
    }

actions

//普通js写法
const changeMode = ({commit},newMode)=> commit('CHANGE_MODE',newMode)

一开始会不知道该从哪里下手修改,这里提供一个思路

//记住action的方法类型名为      Action<当前State类型,根State类型>

//如果store没有分模块,那么直接就写成   Action<当前State类型,当前State类型> 也可以

//写成  Action<State,any>   也可以(使用了tslint会显示warn)

//那么
import {Action} from 'vuex'
const changeMode:Action<State,any>=({commit},newMode)=> commit('CHANGE_MODE',newMode)

//按住ctrl,鼠标左键点击 Action,会跳到类型声明

//显示 export type Action<S, R> = ActionHandler<S, R> | ActionObject<S, R>;

//继续点击 ActionHandler    跳转到它的定义

//定义为    export type ActionHandler<S, R> = (this: Store<R>, injectee: ActionContext<S, R>, payload?: any) => any;

//这就是action函数的格式要求。查看参数要求,第一个this为当前对象,忽视。第二个injectee就是我们平时使用的commit的父类。第三个payload自然就是参数了。

//跳转到injectee的格式ActionContext的声明

//看到以下内容。可以看到属性中的commit
/*
export interface ActionContext<S, R> {
  dispatch: Dispatch;
  commit: Commit;
  state: S;
  getters: any;
  rootState: R;
  rootGetters: any;
}
*/

//接下来就可以写了
//首先是最直接的,从vuex 获取 ActionContext
import {  ActionContext } from 'vuex';
...
const changeMode: Action<State, State> = (context: ActionContext<State, State>, newMode: number) =>
  context.commit('CHANGE_MODE', newMode);
//测试,搞定

//当然也可以秀一波解构赋值,因为context内我们只使用到了Commit。当然也要引入Commit
const changeMode: Action<State, State> = (context: { commit: Commit }, newMode: number) =>
  context.commit('CHANGE_MODE', newMode);

以上就是vuex的主要难点,剩下的就是为变量写接口,分离,引入,测试之类的事情了。

组件

以一个组件为例子

组件结构

Group
    props
        group
    data
        groupData
        showList
    computed
        curMode
    methods
        toggle
    hook
        created
    watch
        group

因为是把已有的项目更改为ts,所以模板部分和样式部分原封不动的复制
修改部分为script标签

1.因为我这次选择的是基于类的写法。所以从插件中获取基类。
import { Vue, Component } from 'vue-property-decorator';

2.script标签修改成ts
<script lang="ts">

3.添加@Component,组件名,如果有子组件也在此引入
@Component({
  name:"xxx",
  components:{
    //子组件
  }
})

4.添加props。因为貌似vue2.x对ts支持并不完全。props是以创建一个带有props的父类,再继承它来实现的
    const XxxProps = Vue.extend({
    props: ['group'],
    })

    //并修改导出。如果没有props 那么,extends Vue
    export default class Xxx extends XxxProps{}

//ps,如果要进行prop类型检验,且类型为自定义接口类型

import { Group  } from '@/store/state';
import { PropType } from 'vue';
const ItemProps = Vue.extend({
  props: {
    item: Object as PropType<Group>,
  },
});

5.data
data(){
  return{
    aaa:10,
    bbb:11
  }
}
改为:
export default class Xxx extends XxxProps{
  private groupData = 10
  private showList = 11   
}

6.methods,把内部函数直接提出来,
    methods:{
        toggle(){}
    }
改为:
    toggle(){}

7.computed
computed:{
  //get
  curMode(){},
  //假设有 set YYY
  YYY(){},
}
改成:
get curMode(){}
set YYY(){}

8.钩子不需要修改,把逗号去掉就行了
    created()

9.watch
watch:{
  aaa(){}
}
改成:
@Watch('aaa')
onAaaChanged(newVal){}
ps.需要从 vue-property-decorator 引入Watch

组件格式

<script lang="ts">
import { Vue, Component, Watch } from 'vue-property-decorator';
import { PropType } from 'vue';
import Item from '@/components/Item.vue';
import { List } from '@/store/IFs';

const GroupProps = Vue.extend({
  props: {
    group: Object as PropType<List>,
  },
});
@Component({
  name: 'Group',
  components: {
    Item,
  },
})
export default class Group extends GroupProps {
  private groupData: List = {};
  private showList = true;
  get curMode() {}
  del() {}
  toggle() {}
  created() {}
  @Watch('group')
  onGroupChange(newValue: List) {}
}
</script>

相关文档

基于类的vue api 基础
https://class-component.vuejs.org/guide/class-component.html#data
上面的扩展(@watch之类的)
https://www.npmjs.com/package/vue-property-decorator
ts 文档
https://www.tslang.cn/docs/home.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值