vue+TypeScript須要注意的點

一.引入TypeScript

// ts-loader typescript 必須安裝,其餘的相信你之後也會裝上的
npm i ts-loader typescript tslint tslint-loader tslint-config-standard --save-dev
複製代碼
  • ts-loader:TypeScript 爲 Webpack 提供了 ts-loader,其實就是爲了讓webpack識別 .ts .tsx文件
  • tslint-loader跟tslint:我想你也會在.ts .tsx文件 約束代碼格式(做用等同於eslint)
  • tslint-config-standard:tslint 配置 standard風格的約束

二.修改webpack配置文件(webpack.base.conf.js)

1.入口文件修改成main.ts

entry: {
    app: './src/main.ts'
}
複製代碼

2.擴展名resolve.extensions新增.ts後綴

extensions: ['.js', '.vue', '.json', '.ts']
複製代碼

3.添加解析ts文件的規則

{
      test: /\.ts$/,
      exclude: /node_modules/,
      enforce: 'pre',
      loader: 'tslint-loader',
},
{
      test: /\.tsx?$/,
      loader: 'ts-loader',
      exclude: /node_modules/,
      options: {
         appendTsSuffixTo: [/\.vue$/]
      }
}
複製代碼

三:添加 tsconfig.json

ts-loader 會檢索當前目錄下的 tsconfig.json 文件,根據裏面定義的規則來解析.ts文件(就跟.babelrc的做用同樣)javascript

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

四:添加 tslint.json

{
    "extends": "tslint-config-standard",
    "globals": {
      "require": true
    },
    "rules": {
      "arrow-return-shorthand": true,
      "callable-types": true,
      "class-name": true,
      "comment-format": [
        true,
        "check-space"
      ],
      "curly": true,
      "deprecation": {
        "severity": "warn"
      },
      "eofline": true,
      "forin": true,
      "import-blacklist": [
        true,
        "rxjs",
        "rxjs/Rx"
      ],
      "import-spacing": true,
      "indent": [
        true,
        "spaces"
      ],
      "interface-over-type-literal": true,
      "label-position": true,
      "max-line-length": [
        true,
        140
      ],
      "member-access": false,
      "member-ordering": [
        true,
        {
          "order": [
            "static-field",
            "instance-field",
            "static-method",
            "instance-method"
          ]
        }
      ],
      "no-arg": true,
      "no-bitwise": true,
      "no-console": [
        true,
        "debug",
        "info",
        "time",
        "timeEnd",
        "trace"
      ],
      "no-construct": true,
      "no-debugger": true,
      "no-duplicate-super": true,
      "no-empty": false,
      "no-empty-interface": true,
      "no-eval": true,
      "no-inferrable-types": [
        true,
        "ignore-params"
      ],
      "no-misused-new": true,
      "no-non-null-assertion": true,
      "no-shadowed-variable": true,
      "no-string-literal": false,
      "no-string-throw": true,
      "no-switch-case-fall-through": true,
      "no-trailing-whitespace": true,
      "no-unnecessary-initializer": true,
      "no-unused-expression": true,
      "no-use-before-declare": true,
      "no-var-keyword": true,
      "object-literal-sort-keys": false,
      "space-before-function-paren": ["error", "never"],
      "ter-indent": 4,
      "one-line": [
        true,
        "check-open-brace",
        "check-catch",
        "check-else",
        "check-whitespace"
      ],
      "prefer-const": true,
      "quotemark": [
        true,
        "single"
      ],
      "radix": true,
      "semicolon": [
        true,
        "always"
      ],
      "triple-equals": [
        true,
        "allow-null-check"
      ],
      "typedef-whitespace": [
        true,
        {
          "call-signature": "nospace",
          "index-signature": "nospace",
          "parameter": "nospace",
          "property-declaration": "nospace",
          "variable-declaration": "nospace"
        }
      ],
      "typeof-compare": true,
      "unified-signatures": true,
      "variable-name": false,
      "whitespace": [
        true,
        "check-branch",
        "check-decl",
        "check-operator",
        "check-separator",
        "check-type"
      ]
    }
  }	
複製代碼

五:讓 ts 識別 .vue

因爲 TypeScript 默認並不支持 *.vue 後綴的文件,因此在 vue 項目中引入的時候須要建立一個 vue-shim.d.ts 文件,放在項目項目對應使用目錄下,例如 src/vue-shim.d.tshtml

declare module "*.vue" {
  import Vue from "vue";
  export default Vue;
}	  
複製代碼

意思是告訴 TypeScript *.vue 後綴的文件能夠交給 vue 模塊來處理。vue

而在代碼中導入 *.vue 文件的時候,須要寫上 .vue 後綴。緣由仍是由於 TypeScript 默認只識別 *.ts 文件,不識別 *.vue 文件:java

import Component from 'components/component.vue'     
複製代碼

六:改造vue-router

由於 ts 沒法識別 require,因此按需加載路由的時候須要安裝聲明文件npm i @types/webpack-env -save-dev;而後才能夠用const rank = r => require.ensure([], () => r(require('../pages/rank/rank')), 'rank'); 這樣的寫法;node

七:開始修改App.vue文件

  • 在script 標籤上加上 lang="ts", 意思是讓webpack將這段代碼識別爲typescript 而非javascript
  • 修改vue組件的構造方式( 跟react組件寫法有點相似, 詳見官方 ), 以下圖
  • 用vue-property-decorator語法改造以前代碼
<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-view/>
  </div>
</template>

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

@Component({})
export default class App extends Vue {
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

</style>
複製代碼

八:改造 .vue 文件

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

  • vue-class-component:強化 Vue 組件,使用 TypeScript/裝飾器 加強 Vue 組件
  • vue-property-decorator:在 vue-class-component 上加強更多的結合 Vue 特性的裝飾器

1.vue-class-component

vue-class-component 對 Vue 組件進行了一層封裝,讓 Vue 組件語法在結合了 TypeScript 語法以後更加扁平化:jquery

<template>
  <div>
    <input v-model="msg">
    <p>msg: {{ msg }}</p>
    <p>computed msg: {{ computedMsg }}</p>
    <button @click="greet">Greet</button>
  </div>
</template>

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

  @Component
  export default class App extends Vue {
    // 初始化數據
    msg = 123

    // 聲明週期鉤子
    mounted () {
      this.greet()
    }

    // 計算屬性
    get computedMsg () {
      return 'computed ' + this.msg
    }

    // 方法
    greet () {
      alert('greeting: ' + this.msg)
    }
  }
</script>
複製代碼

使用時須要注意的問題webpack

問題1: ts 沒法識別$ref

解決辦法:es6

  • 直接在 this.refs.xxx 後面申明類型如:this.refs.lyricsLines as HTMLDivElement;
  • 在export default class xxx extends Vue裏面聲明所有的$ref 的類型
$refs: {
    audio: HTMLAudioElement,
    lyricsLines: HTMLDivElement
}
複製代碼

問題2: 怎麼把mixin引入

@Component({
	/*components: {
    	Swipe
	},*/
    mixins: [mixin]
})
複製代碼

2.vue-property-decorator

vue-property-decorator 是在 vue-class-component 上加強了更多的結合 Vue 特性的裝飾器,新增了這 7 個裝飾器:web

  • @Emit
  • @Inject
  • @Model
  • @Prop
  • @Provide
  • @Watch
  • @Component (從 vue-class-component 繼承)

在這裏列舉幾個經常使用的@Prop/@Watch/@Component

import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from 'vue-property-decorator'

@Component
export class MyComponent extends Vue {
  
  @Prop()
  propA: number = 1

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

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

  @Prop({ type: null })
  propD: any

  @Watch('child')
  onChildChanged(val: string, oldVal: string) { }
}
複製代碼

上面的代碼至關於:

export default {
  props: {
    checked: Boolean,
    propA: Number,
    propB: {
      type: String,
      default: 'default value'
    },
    propC: [String, Boolean],
    propD: { type: null }
  }
  methods: {
    onChildChanged(val, oldVal) { }
  },
  watch: {
    'child': {
      handler: 'onChildChanged',
      immediate: false,
      deep: false
    }
  }
}	
複製代碼

九:注意點

1.若是你引用第三方無類型聲明的庫,那就須要本身編寫x.d.ts文件

2.若是引用 ui 組件的時候,若是控制檯出現Property '$xxx' does not exist on type 'App'的話,那麼能夠在vue-shim.d.ts增長

declare module 'vue/types/vue' {
  interface Vue {
    $xxx: any,
  }
}
複製代碼

其餘相似的報錯:好比我寫了一個自定義的權限指令 在vue文件中直接this.auth會報錯Property 'auth' does not exist on type 'orderList'.

解決辦法:(this as any).auth('TESTXMC_order-status-index');

3.如何全局使用window的變量??

declare global{
    interface Window {
        DEBUG: string;
        API_HOST: string
    }
}  

(window as any).DEBUG = 'dev';        
複製代碼

4.如何引入jquery?

npm install --save jquery
npm install --save-dev @types/jquery
複製代碼

在index.html裏面引入

<script src="node_modules/jquery/dist/jquery.js"></script>
複製代碼
相關文章
相關標籤/搜索