[聚合文章] TypeScript + Vue系列(一): 新项目配置

vue.js 2018-01-12 29 阅读

友情提示!!!

如下图所示, vue-cli将在下个版本提供开箱即用的TypeScript的脚手架. 在你阅读文章前, 请检查Vue官方文档: TypeScript支持.
如果官方已经提供了脚手架, 下面文章就可以不用看了. 去vue-cli开箱一个typescript + vue的模板吧!!!

前言

Vue2.5版本的升级中, Vue已经大大的改进了对于类的支持. 但是目前在Vue中使用TypeScript依然需要开发者做一些配置和引入第三方的库(例如官方推荐的vue-class-component). 本文就是基于vue-cli初始化项目后, 配置TypeScript所需要的相关步骤.

本位提供了示例代码 , 读者可以在配置的过程进行比对:
master分支为完整代码;
baseConfig分支提供了TypeScript的配置;
extension-example为引入了vue-class-component的代码;

初始化项目

1.使用vue-cli初始化webpack模板, 并安装该模板所需要的依赖文件

$ vue init webpack vue-typescript-start

2.使用npmcnpm安装typescript相关依赖

npm i --save-dev typescript ts-loader

配置TypeScript

修改Webpack配置项

修改目录下build/wepback.base.conf.js文件

  • 修改入口文件为main.ts, 并顺便在src/下将main.js修改成main.ts
entry: {
  app: './src/main.ts'
}
  • resolve.extensions中添加上.ts后缀(未来引入.ts就可以不再写后缀了)
  resolve: {
    extensions: ['.js', '.vue', '.json', '.ts'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  }
  • modules>rules中添加ts-loader
  {
    test: /\.tsx?$/,
    loader: 'ts-loader',
    exclude: /node_modules/,
    options: {
      appendTsSuffixTo: [/\.vue$/],
    }
  }

添加vue-shim.d.ts文件

在src目录下新建一个文件vue-shim.d.ts, 用于识别单文件vue内的ts代码


declare module "*.vue" {
  import Vue from "vue";
  export default Vue;
}

添加tsconfig.json文件

在项目的根目录下添加tsconfg.json文件, 该文件描述了该项目是一个TypeScript项目, ts-loader将会根据该配置信息进行TypeScript的编译, 下面是我的配置文件作为参考, 全部的配置参见官方配置文档

{
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules"
  ],
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true, 
    "allowJs": true,
    "module": "esnext",
    "target": "es5",
    "moduleResolution": "node",
    "isolatedModules": true,
    "strictFunctionTypes": false,
    "lib": [
      "dom",
      "es5",
      "es6",
      "es7",
      "es2015.promise"
    ],
    "sourceMap": true,
    "pretty": true
  }
}

其他修改

  • 重命名src/router/中的index.jsindex.ts,src/下的mian.js修改为mian.ts, 并将.vue文件的引入添加后缀(在)
import App from './App.vue'
  • 修改src下的App.vue文件中的<script>语言为ts
<script lang="ts">
  • 修改src/compontents/HelloWorld.vue代码, 让它变得更清爽和更应主题一点吧!

<template>
  <div class="hello">
    <h1>{{msg}} </h1>

  </div>
</template>

<script lang="ts">
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: '欢迎使用TypeScript + Vue'
    }
  }
}
</script>

启动TypeScript + Vue的应用

执行npm run dev, 访问localhost:8080端口, Vue脚手架启动成功, 现在我们已经成功的在基于vue-cli创建的项目中, 引入了TypeScript!

到此处的代码为: baseConfig分支

使用扩展组件

上面已经将TypeScript集成到了Vue框架中, 但是到目前为止, 如果想写TypeScript我们还必须借助一些第三方的类库, 例如前面提到的vue-class-componentvue-property-decorator. 也许有读者疑惑为什么要使用这些第三方类库? 我们可以用HelloWorld.vue组件的代码说明:

<script lang="ts">
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: '欢迎使用TypeScript + Vue'
    }
  }
}
</script>

其中msg这个属性显而易见是string的类型, 按照TypeScript的写法, 我们理应将其加上类型定义, 所以这一行代码就变成了msg: string: '欢迎使用TypeScript + Vue'. 这样写既不符合TypeScript的语法, 也不符合Vue的语法. 所以一些聪明的开发者, 引入了ES7中的装饰器, 解决了这个问题.

安装依赖

安装vue-class-componentvue-property-decorator

npm i vue-class-component vue-property-decorator --save

基于vue-class-componet改写.vue

vue-class-component提供了@Component装饰器来抒写.vue文件. 下面以示例代码说明其用法

  • 改写App.vue
<script lang="ts">
import Vue from 'vue';
import Component from "vue-class-component";

@Component
export default class App extends Vue{
  name:string =  'app';
}
</script>

上述就是引入了vue-class-component@Component装饰器后.vue文件的写法. 你可以看到的是, 我们去掉了data(){ return { ... } }等函数. 引入@Component装饰器后, 可以让我们写.vue组件更加的扁平化. 你也许通过改写App.vue无法感受到其优点, 那么通过下面的例子, 我相信你会有一种全新的写.vue文件的体验.

  • 改写HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{msg}}</h1>
    <h3>今年是: {{yearNumber}} 年</h3>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";

@Component
export default class HelloWorld extends Vue {
  //初始化data
  msg: string = "欢迎使用TypeScript + Vue";
  user: string = "亲爱的Vuer";
  yearNumber: number;

  //mounted钩子
  mounted(): void {
    this.greet(this.user);
  }

  //created钩子
  created(): void {
    this.yearNumber = 2018;
  }

  //methods定义方法
  greet(user: string): void {
    alert(user + ", 你好!");
  }
}
</script>

通过上面的例子, 相信你已经完全体会到了使用vue-class-component提供的@Component抒写Vue代码的简洁. 如果想更多的了解这个库, 可查看官方提供的example

到此处的代码为: extension-example分支

vue-property-decorator的用法

vue-property-decorator是一个依赖于vue-class-component的库, 它在@Component这个装饰器的基础上新增了6个装饰器, 下面以官方提供的示例代码说明其用法

  • 使用了vue-property-decorator.vue文件
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 }

  @Inject() foo: string
  @Inject('bar') bar: string
  @Inject(s) baz: string

  @Model('change') checked: boolean

  @Prop()
  propA: number

  @Prop({ default: 'default value' })
  propB: string

  @Prop([String, Boolean])
  propC: string | boolean

  @Provide() foo = 'foo'
  @Provide('bar') baz = 'bar'

  @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',
  inject: {
    foo: 'foo',
    bar: 'bar',
    [s]: s
  },
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean,
    propA: Number,
    propB: {
      type: String,
      default: 'default value'
    },
    propC: [String, Boolean],
  },
  data () {
    return {
      foo: 'foo',
      baz: 'bar'
    }
  },
  provide () {
    return {
      foo: this.foo,
      bar: this.baz
    }
  },
  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
    }
  }
})

示例代码

1. Github仓库

TypeScript相关文档

1. TypeScript入门教程

2. TypeScript官网

参考文章

1. Decorators in ES7: ES7中装饰器

2. ES7 Decorator 装饰者模式

3. vue + typescript 新项目起手式

4. vue + typescript 进阶篇

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。