此文已由作者张汉锐授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

前言:对于我们而言,typescript 更像一个工具

官方指南

从 vue2.5 之后,vue 对 ts 有更好的支持。根据官方文档,vue 结合 typescript ,有两种书写方式:

Vue.extend

  import Vue from 'vue'

  const Component = Vue.extend({    // type inference enabled
  })

Class-style Vue Components

  import Vue from 'vue'
  import Component from 'vue-class-component'   // The @Component decorator indicates the class is a Vue component
  @Component({    // All component options are allowed in here
    template: '<button @click="onClick">Click!</button>'
  })
  export default class MyComponent extends Vue {    // Initial data can be declared as instance properties
    message: string = 'Hello!'     // Component methods can be declared as instance methods
    onClick (): void {      window.alert(this.message)
    }
  }

理想情况下,Vue.extend 的书写方式,是学习成本最低的。在现有写法的基础上,几乎 0 成本的迁移

// 现在常见的写法export default {    // your code }

但「理想丰满,现实骨感」,问题出在:

  • Vue.exend 在和 vuex 和 mixins 结合使用的时候,无法发挥 ts 的作用,vuex 和 mixins 会在项目中大量使用,这个问题不能忽视。

Vue.extend + vuex + mixins 问题的介绍

Vue.extend + vuex 的问题

由于 vuex 使用  mapState, mapActions 等方法的时候,通过字符串形式做映射,这个过程中,丢失了类型信息。下面的 gif 可以看到,整个过程中:

  • 无法做代码提示

  • 无法对对应的 actions  和 state 做类型声明,使得类型检查生效

  • 无法使用重构

显然,如果只有一部分的方法和属性得到了代码提示和类型检查,就是失去了使用 typescript 意义。

在 Vue.extend + vuex 写法下,这个问题暂时没有解决方案。

Vue.extend + mixins 的问题

同样的问题,在 mixin 中定义的方法,不会被 typescript 识别到,下面 gif 可以看到,不仅仅「代码提示」「类型检查」「代码重构」没有工作,甚至因识别不到 test 而报错

Class-Style Components

那么就剩下 Class-Style Components 方案。当然,这个方案需要做额外的工作才能够让「vue 全家桶 + ts」良好的工作。

原理:将属性直接挂载在 class 上,使得 typescript 能够良好的进行「代码提示」和「类型检查」。然后再通过装饰器将属性转成 vue 上的属性。

例如 @Prop, @Watch, @Action 等装饰器,将属性做相应的转换成 props,  watch, mapActions 里面的值,具体后面例子展示。

vue-class-component

这里库提供最基础的 vue 装饰器:@Component 。其他的 vue 装饰器库,都在这个库的基础上做扩展和修改。看看官网的例子:

import Vue from 'vue'import Component from 'vue-class-component'// @Component 会将 MyComponent 中的属性,转换成 vue 对应的属性@Component({  // Vue 所有的属性都可以在这里声明,一般用到的比较少
  template: '<button @click="onClick">Click!</button>'})
export default class MyComponent extends Vue {  // @Component 将 message 转成成 data 
  message: string = 'Hello!'   // @Component 会将这里的 getter 属性,转换成 computed
  get name(){    return 'anders'
  }  // @Component 识别到 created 是声明周期关键字,不做处理
  created(){}  // @Component 识别到 onClick 不是关键字,将它转成 methods  
  onClick (): void {    window.alert(this.message)
  }
}

vue-property-decorator

这个库提供了:

  • @Emit

  • @Inject

  • @Model

  • @Prop

  • @Provide

  • @Watch

其中常用的: @Prop,@Watch,@Emit。 看例子:

import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from 'vue-property-decorator'const s = Symbol('baz')

@Component
export class MyComponent extends Vue {   @Emit()
  addToCount(n: number){ this.count += n }   @Emit('reset')
  resetCount(){ this.count = 0 }   @Prop()
  propA: number   @Prop({ default: 'default value' })
  propB: string   @Prop([String, Boolean])
  propC: string | boolean   @Watch('child')
  onChildChanged(val: string, oldVal: string) { }   @Watch('person', { immediate: true, deep: true })
  onPersonChanged(val: Person, oldVal: Person) { }
}

上面的使用就相当于:

const s = Symbol('baz')

export const MyComponent = Vue.extend({
  name: 'MyComponent',   props: {
    checked: Boolean,
    propA: Number,
    propB: {
      type: String,      default: 'default value'
    },
    propC: [String, Boolean],
  },   methods: {
    addToCount(n){      this.count += n      this.$emit("add-to-count", n)
    },
    resetCount(){      this.count = 0
      this.$emit("reset")
    },
    onChildChanged(val, oldVal) { },
    onPersonChanged(val, oldVal) { }
  },
  watch: {    'child': {
      handler: 'onChildChanged',
      immediate: false,
      deep: false
    },    'person': {
      handler: 'onPersonChanged',
      immediate: true,
      deep: true
    }
  }
})

更加全面的用法参考文档:vue-property-decorator

免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击

相关文章:
【推荐】 iOS安装包瘦身(上篇)

使用 typescript ,提升 vue 项目的开发体验(1)的更多相关文章

  1. 使用 typescript ,提升 vue 项目的开发体验(2)

    此文已由作者张汉锐授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. vuex-class 提供了和 vuex 相关的全部装饰器,从而解决了上面 Vue.extend + vue ...

  2. TypeScript编写Vue项目结构解析

    使用TypeScript编写Vue项目也已经有了一段时间,笔者在刚刚使用TypeScript时候也是很茫然,不知道从何下手,感觉使用TypeScript写项目感觉很累赘并不像JavaScript那么灵 ...

  3. vue项目的开发

    vue项目的开发 我们已经通过命令行创建了一个vue项目,并且打开了这个项目.下面是这个文件的src文件夹,这个文件夹放了整个项目的核心代码. 一.vue文件的用处简介. 1.assets文件夹,用来 ...

  4. 如何加快Vue项目的开发速度

    如何加快Vue项目的开发速度 本文摘自奇舞周刊,侵权删. 现如今的开发,比如内部使用的管理平台这种项目大都时间比较仓促.实际上来说,在使用了webpack + vue 这一套来开发的话已经大大了提高了 ...

  5. 基于Typescript的Vue项目配置国际化

    基于Typescript的Vue项目配置国际化 简介 使用vue-i18n插件对基于Typescript的vue项目配置国际化,切换多种语言, 配合element-ui或者其他UI库 本文以配置中英文 ...

  6. 教你搭建基于typescript的vue项目

    自尤大去年9月推出vue对typescript的支持后,一直想开箱尝试,对于前端sr来说,vue的顺滑加上ts的面向对象,想着就非常美好~ 终于在两个月前,找到了个机会尝试了一把vue+ts的组合. ...

  7. 手动搭建webpack + vue项目之初体验

    在使用vue做开发时,大部分人只会使用官方提供的脚手架搭建项目,脚手架虽然很好用,但想要成为一名优秀的前端开发者,webpack这一道坎是绕不开的,所以我们要学会脱离脚手架,利用webpack手动搭建 ...

  8. 使用TypeScript创建Vue项目

    Vue的灵活性总是让代码看起来非常洗练,对TypeScript来说也是一种挑战, 好在Vue对TypeScript进行了一次全方位的适配. 相对于React严谨的代码,Redux啰嗦的样板代码,Vue ...

  9. 加快Vue项目的开发速度

    巧用Webpack Webpack是实现我们前端项目工程化的基础,但其实她的用处远不仅仅如此,我们可以通过Webpack来帮我们做一些自动化的事情.首先我们要了解require.context()这个 ...

随机推荐

  1. CentOS下安装桌面环境

    1. 使用 yum grouplist 查看可用的 group 2. 使用 yum groupinstall 进行安装.例如:yum groupinstall GNOME Desktop

  2. 微信扫码支付PHP接入总结

    微信扫码支付分为两种模式, 模式一比较复杂,需要公众号配置回调地址. 模式二比较简单,只需要在代码中配置回调地址就可以了. 我这次使用的是模式二. 需要配置参数, const APPID = 'xxx ...

  3. win10下默认使用福昕打开PDF

    win10为了推他的edge浏览器, 将默认的pdf打开设置为了edge浏览器, 非常令人反感, 做浏览器就好好做浏览器, 为什么要默认打开pdf? 而且修改默认为福昕后, 下次打开pdf文件, 他又 ...

  4. Py修行路 python基础 (十)装饰器

    装饰器 一.定义 装饰器:顾名思义,就是对某个东西起到装饰修饰的功能. python中的装饰器,其本质上就是一个python函数,它可以让其他函数在不需要任何代码变动的前提下增加额外功能.通俗理解就是 ...

  5. phpStudy启动失败时的解决方法 提示缺vc9运行库

    问题描述: 问题产生原因分析: php5.3.5.4和apache都是用vc9编译,电脑必须安装vc9运行库才能运行. php5.5.5.6是vc11编译,如用php5.5.5.6必须安装vc11运行 ...

  6. leetcode788

    public class Solution { public int RotatedDigits(int N) { ; ; i <= N; i++) { var str = i.ToString ...

  7. winform问题集锦

    正试图在 os 加载程序锁内执行托管代码.不要尝试在 DllMain 或映像初始化函数内运行托管代码 说明 .NET2.0中增加了42种非常强大的调试助手,MDA.Loaderlock 是其中之一.L ...

  8. spark 中文编码处理

    日志的格式是GBK编码的,而hadoop上的编码是用UTF-8写死的,导致最终输出乱码. 研究了下Java的编码问题. 网上其实对spark输入文件是GBK编码有现成的解决方案,具体代码如下 impo ...

  9. easylogging++学习记录(二):流式日志

    easylogging++日志库流式日志的写入,依赖于el::base::Writer类的析构,以debug日志为例:具体代码如下: #define LOG(LEVEL) CLOG(LEVEL, EL ...

  10. Android适配器Adapter的学习

    Android中有很多的适配器,首先看看这些适配器的继承结构 这些适配器中,BaseAdapter用的最多,也用的最熟,先放过他,从ArrayAdapter开始 一个listAdapter用来管理一个 ...