vue + typescript 进阶篇

本文是继 Vue + TypeScript 新项目起手式 以后的进阶 + 踩坑配置,因此推荐先阅读前文 javascript

完整阅读完以后,基本能够顺利在新项目中使用vue + typescripthtml

另外特别注意!!! vue

不推荐在已有项目上强加 typescript, 因ts写法的组件跟以前的组件不兼容,若上的话须要修改以前写的组件 java

配置完整版可参考 vue-typescript-starter,若没配置出来,也能够对照修改配置node

直接进入正题:jquery

概览

  • ts 支持 render jsx 写法
  • ts 支持 es6 / es67
  • 配置 vuex
  • vue 识别全局方法/变量
  • 支持 mixin
  • 支持 ProvidePlugin 的全局变量,好比 lodash_

支持 render jsx 写法

这里一共分两步webpack

  1. 首先得先让 vue 支持 jsx 写法
  2. 再让 vue 中的 ts 支持 jsx 写法

让 vue 支持 jsx

按照官方作法,安装Babel 插件git

安装依赖es6

npm install\
  babel-plugin-syntax-jsx\
  babel-plugin-transform-vue-jsx\
  babel-helper-vue-jsx-merge-props\
  babel-preset-es2015\
  --save-dev复制代码

.babelrc中添加:github

{
  "plugins": ["transform-vue-jsx"]
}复制代码

以后就能够这些写render,以下图:

让 ts 支持 jsx

首先配置 webpack
找到./build/webpack.base.conf.js

  • 找到resolve.extensions 里面加上.tsx 后缀
resolve: {
    extensions: ['.js', '.vue', '.json', '.ts', '.tsx']
  }复制代码
  • 找到module.rules 修改webpack对.tsx .ts 的解析
module: {
    rules: [
      {
        test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        enforce: 'pre',
        include: [resolve('src'), resolve('test')],
        options: {
          formatter: require('eslint-friendly-formatter')
        }
      },
        // 从这里复制下面的代码就能够了
        // 若是以前按照起手式配置的同窗,请替换配置
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        enforce: 'pre',
        loader: 'tslint-loader'
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: Object.assign(vueLoaderConfig, {
          loaders: {
            ts: "ts-loader",
            tsx: "babel-loader!ts-loader"
          }
        })
      },
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        use: [
          "babel-loader",
          {
            loader: "ts-loader",
            options: { appendTsxSuffixTo: [/\.vue$/] }
          }
        ]
      },
      // 复制截止
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test')]
      },复制代码

上面的配置,主要意思是 vue 文件识别ts/tsx代码的时候,先过一遍ts-loader,在过一遍babel-loader,我知道这听起来有点蠢,可是jsx不能不要对吧?

而后在 tsconfig.json中,添加对jsx的支持

"compilerOptions": {
    "jsx": "preserve"
    }复制代码

以后就能够顺利在.vue单文件中的tsjsx代码了,以下图所示:

敲黑板,这里又有重点,使用 jsx 写法的话, 必定要使用 .tsx,不要用.ts了,切记!!!

支持es6 / es7

tsconfig.json中,添加对es6 / es7的支持,更多的配置请见tsconfig - 编译选项

"lib": [
      "dom",
      "es5",
      "es6",
      "es7",
      "es2015.promise"
    ]复制代码

否则的话,连Object.assign 这种最基本的函数也会在ts中报错,真的使人难过

配置 vuex

这里就比较简单了

# 安装依赖
npm i vuex vuex-class --save复制代码
  • vuex:在 vue 中集中管理应用状态
  • vuex-class :在 vue-class-component 写法中 绑定 vuex

Store的配置跟原来如出一辙,引用的时候有一点区别,下面的例子介绍了用法,应该一看便知,这里我不作赘述

import Vue from 'vue'
import Component from 'vue-class-component'
import {
  State,
  Getter,
  Action,
  Mutation,
  namespace
} from 'vuex-class'

const ModuleGetter = namespace('path/to/module', Getter)

@Component
export class MyComp extends Vue {
  @State('foo') stateFoo
  @State(state => state.bar) stateBar
  @Getter('foo') getterFoo
  @Action('foo') actionFoo
  @Mutation('foo') mutationFoo
  @ModuleGetter('foo') moduleGetterFoo

  // If the argument is omitted, use the property name
  // for each state/getter/action/mutation type
  @State foo
  @Getter bar
  @Action baz
  @Mutation qux

  created () {
    this.stateFoo // -> store.state.foo
    this.stateBar // -> store.state.bar
    this.getterFoo // -> store.getters.foo
    this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true })
    this.mutationFoo({ value: true }) // -> store.commit('foo', { value: true })
    this.moduleGetterFoo // -> store.getters['path/to/module/foo']
  }
}复制代码

让 vue 识别全局方法/变量

在项目中使用 ui 组件是很正常的操做

好比使用 Element-uImeesage,用法以下图:

this.$message({
    message: '恭喜你,这是一条成功消息',
    type: 'success'
  })复制代码

可是在配置了 typescript以后

那是由于 $message属性,并无在 vue实例中声明

解决办法也很是简单,那咱们就声明一下呗

在以前文章中建立的 src/vue-shim.d.ts文件中,增长以下代码:

// 声明全局方法
declare module 'vue/types/vue' {
  interface Vue {
    $Message: any,
    $Modal: any
  }
}复制代码

这样,以后再使用this.$message()的话就不会报错了

支持 mixin

我在vue-property-decorator里里外外找了好几圈,缺没有找到mixin这个修饰器

// 若是全局mixin,那也太蠢了
 Vue.mixin( mixin )复制代码

找很是多的 ts + vue 项目,可是没有找到我理想的mixin的方式,
那么就本身进行探索咯,下图是我本身使用的目前最佳mixin方式:

声明了一个mixin组件,以下图:

其实就是我在mixin中声明了声明属性 / 方法,那么我就在vue实例中声明这个属性 / 方法

使用方式以下图:

支持 ProvidePlugin 的全局变量,好比 lodash 的 _

若是咱们在项目中有使用 jquery,lodash 这样的工具库的时候,确定不但愿在全部用到的地方都import _ from ‘lodash’
@types/lodash

那咱们就来配置一下:

首先仍是在webpack.base.conf.js 中添加一个插件、并把这个 vendor拉出来

entry: {
    app: './src/main.ts',
    vendor: [
      "lodash"
    ]
  }

  plugins: [
    new webpack.ProvidePlugin({
      _: 'lodash'
    })
  ]复制代码

上面的意思是,当模块使用这些变量的时候wepback会自动加载

而后,你须要告诉eslint这个 _ 是全局的

.eslintrc.js中添加

globals: {
    _: true
  },复制代码

接下来,你还须要告诉ts这个 _ 是全局的

vue-shim.d.ts

declare global {
  const _: typeof lodash
}复制代码

若是没有上面这段声明,可是在 ts 中使用的话,会报以下的错误:

这个问题Consider allowing access to UMD globals from modules · Issue #10178 · Microsoft/TypeScript · GitHub

有一个很简单的解释,就是惧怕你全局声明的_import _ from 'lodash' 的行为不一致,这样的话,以后会留下隐患

到这里,本文的配置就到此结束

最后

本文的这些配置都是在新项目开发中,一步步用血汗踩出来的

目测已经涵盖了大部分的使用问题,若是有其余的意见或建议的话,欢迎在本文下面评论~~

再发一次,配置完整版可参考 vue-typescript-starter,若没配置出来,也能够对照修改配置

在刚上typescript的时候,我是拒绝的,嫌弃每一个地方都要声明类型,否则就走不下去,可是若是让大家作如下一个选择题:

  • 在编译时发现问题
  • 仍是运行时发现问题

我会坚决果断选择前者,这是ts强类型带给我最大的亮点

参考连接/推荐阅读

相关文章
相关标签/搜索