Vue-TypeScript全面教程(附例項程式碼和一鍵構建工具)

SimonZhang發表於2017-12-19

功能

  • 輪播
  • 搜尋
  • 列表
  • 懶載入
  • 簡單動畫
  • loading
  • vue-router.ts
  • vuex.ts
  • vue-class-component使用
  • vuex-class使用
  • xxx.d.ts宣告檔案
  • 基於類的編寫方式
  • mock資料
  • tsconfig.json
  • webpack配置
  • vue-typescript-cli

專案地址:github.com/SimonZhangI…

歡迎提建議,覺得不錯的給個star~

完成後的簡單例子

基於類的寫法加上靜態型別檢查,簡直不能再嗨

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

@Component
export default class Shops extends Vue {
  @State shops: StoreState.shop[];
  @State searchVal: string;

  get shopList(): StoreState.shop[] {
    const shops = this.shops;
    const searchVal = this.searchVal;
    return shops.filter(
      (el: StoreState.shop) => el.shopName.indexOf(searchVal) > -1
    );
  }
}
</script>
複製程式碼

為什麼使用TypeScript

1. JavaScript的超集

支援所有原生JavaScript的語法

2. 強型別語言

現在很多主流語言都是強型別的,而這點也一直是JavaScript所被人詬病的地方。使用TypeScript之後,將會在程式碼除錯、重構等步驟節省很多時間。

比如說:函式在返回值的時候可能經過複雜的操作,那我們如果想要知道這個值的結構就需要去仔細閱讀這段程式碼。那如果有了TypeScript之後,直接就可以看到函式的返回值結構,將會非常的方便

3. 強大的IDE支援

現在的主流編輯器如VSCodeWebStormAtomSublime等都對TypeScript有著非常友好的支援,主要體現在智慧提示上,非常的方便

4. 可執行於任何瀏覽器、計算機、作業系統

強大的編譯引擎

5. 迭代更新快

不斷更新,提供更加方便友好的Api

6. 微軟和Google爸爸

TypeScript是微軟開發的語言,而Google的Angular使用的就是TypeScript,所以不用擔心會停止維護,至少在近幾年內TypeScript都會一門主流開發語言

7. npm下載量非常高

截止2017.12.17, TypeScript在全球範圍內的npm日均下載量在30w左右,這個數字將近是vue下載量的10倍,可見TypeScript還是非常受歡迎的

Vue-TypeScript-Cli

官方雖然明確提出對TypeScript的支援,但是並沒有明確的配置文件,自己在配置的時候還是需要查閱很多資料以及踩很多坑的(這個過程真的很藍瘦-_-)

但是現在可以不用踩這個坑啦,我基於官方的vue-cli寫了一個vue-typescript-cli,可以一鍵構建TypeScript模板

用法

vue init SimonZhangITer/vue-typescript-template <project-name>
複製程式碼

比如

vue init SimonZhangITer/vue-typescript-template my-project
複製程式碼

然後配置好的TypeScript模板就下載到./my-project資料夾了,npm run dev即可執行

TypeScript配置

這裡記錄一下當時的踩坑過程,所有配置已經在vue-typescript-template配置完畢

1. Webpack

安裝ts-loader

首先需要安裝ts-loader,這是TypeScript為Webpack提供的編譯器,類似於babel-loader

npm i ts-loader -D
複製程式碼

配置rules

接著在Webpack的module.rules裡面新增對ts的支援(我這裡的webpack版本是2.x):

{
    test: /\.vue$/,
    loader: 'vue-loader',
    options: vueLoaderConfig
},
{
    test: /\.ts$/,
    loader: 'ts-loader',
    options: {
      appendTsSuffixTo: [/\.vue$/],
    }
}
複製程式碼

配置extensions

新增可識別檔案字尾對ts的支援,如:

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

2. tsconfig.json

建立tsconfig.json檔案,放在根目錄下,和package.json同級

配置內容主要也看個人需求,具體可以去typescript的官網檢視,但是有一點需要注意:

在Vue中,你需要引入 strict: true (或者至少 noImplicitThis: true,這是 strict 模式的一部分) 以利用元件方法中 this 的型別檢查,否則它會始終被看作 any 型別。

這裡列出我的配置,功能在註釋中給出

{
  "include": [
    "src/*",
    "src/**/*"
  ],
  "exclude": [
    "node_modules"
  ],
  "compilerOptions": {
    // types option has been previously configured
    "types": [
      // add node as an option
      "node"
    ],
    // typeRoots option has been previously configured
    "typeRoots": [
      // add path to @types
      "node_modules/@types"
    ],
    // 以嚴格模式解析
    "strict": true,
    // 在.tsx檔案裡支援JSX
    "jsx": "preserve",
    // 使用的JSX工廠函式
    "jsxFactory": "h",
    // 允許從沒有設定預設匯出的模組中預設匯入
    "allowSyntheticDefaultImports": true,
    // 啟用裝飾器
    "experimentalDecorators": true,
    "strictFunctionTypes": false,
    // 允許編譯javascript檔案
    "allowJs": true,
    // 採用的模組系統
    "module": "esnext",
    // 編譯輸出目標 ES 版本
    "target": "es5",
    // 如何處理模組
    "moduleResolution": "node",
    // 在表示式和宣告上有隱含的any型別時報錯
    "noImplicitAny": true,
    "lib": [
      "dom",
      "es5",
      "es6",
      "es7",
      "es2015.promise"
    ],
    "sourceMap": true,
    "pretty": true
  }
}
複製程式碼

3. 修改main.js

  1. 把專案主檔案main.js修改成main.ts,裡面的寫法基本不變,但是有一點需要注意: 引入Vue檔案的時候需要加上.vue字尾,否則編輯器識別不到

  2. 把webpack的entry檔案也修改成main.ts

4. vue-shims.d.ts

TypeScript並不支援Vue檔案,所以需要告訴TypeScript*.vue檔案交給vue編輯器來處理。解決方案就是在建立一個vue-shims.d.ts檔案,建議放在src目錄下再建立一個typings資料夾,把這個宣告檔案放進去,如:src/typings/vue-shims.d.ts,檔案內容:

*.d.ts型別檔案不需要手動引入,TypeScript會自動載入

declare module '*.vue' {
  import Vue from 'vue'
  export default Vue
}
複製程式碼

到這裡TypeScript在Vue中配置就完成了,可以愉快的擼程式碼了~

第三方外掛庫

現在Vue官方已經明確提出支援TypeScript,並考慮出一個對應的vue-cli,在這之前,Vue開發團隊已經開發出了一些外掛庫來支援TypeScript,這裡簡單和大家介紹一下。

Vue-Class-Component

vue-class-component是官方維護的TypeScript裝飾器,寫法比較扁平化。Vue對其做到完美相容,如果你在宣告元件時更喜歡基於類的 API,這個庫一定不要錯過

ps:用了這個裝飾器之後寫方法不需要額外加逗號,賊嗨~~~

import Vue from "vue";
import Component from "vue-class-component";

@Component
export default class App extends Vue {
  name:string = 'Simon Zhang'

  // computed
  get MyName():string {
    return `My name is ${this.name}`
  }

  // methods
  sayHello():void {
    alert(`Hello ${this.name}`)
  }

  mounted() {
    this.sayHello();
  }
}
複製程式碼

這個程式碼如果用原生Vue語法來寫的話就是這樣:

export default {
  data () {
    return {
      name: 'Simon Zhang'
    }
  },

  mounted () {
    this.sayHello()
  },

  computed: {
    MyName() {
      return `My name is ${this.name}`
    }
  },

  methods: {
    sayHello() {
      alert(`Hello ${this.name}`)
    },
  }
}
複製程式碼

Vuex-Class

vuex-class是基於基於vue-class-component對Vuex提供的裝飾器。它的作者同時也是vue-class-component的主要貢獻者,質量還是有保證的。

import Vue from "vue";
import Component from "vue-class-component";
import { State, Action, Getter } from "vuex-class";

@Component
export default class App extends Vue {
  name:string = 'Simon Zhang'
  @State login: boolean;
  @Action initAjax: () => void;
  @Getter load: boolean;

  get isLogin(): boolean {
    return this.login;
  }

  mounted() {
    this.initAjax();
  }
}
複製程式碼

上面的程式碼就相當於:

export default {
  data() {
    return {
      name: 'Simon Zhang'
    }
  },

  mounted() {
    this.initAjax()
  },

  computed: {
    login() {
      return this.$store.state.login
    },
    load() {
      return this.$store.getters.load
    }
  },

  methods: {
    initAjax() {
      this.$store.dispatch('initAjax')
    }
  }
}
複製程式碼

Vue-Property-Decorator

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

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

引入部分第三方庫的時候需要額外宣告檔案

比如說我想引入vue-lazyload,雖然已經在本地安裝,但是typescript還是提示找不到模組。原因是typescript是從node_modules/@types目錄下去找模組宣告,有些庫並沒有提供typescript的宣告檔案,所以就需要自己去新增

解決辦法:在src/typings目前下建一個tools.d.ts檔案,宣告這個模組即可

declare module 'vue-awesome-swiper' {
  export const swiper: any
  export const swiperSlide: any
}

declare module 'vue-lazyload'
複製程式碼

對vuex的支援不是很好

在TypeScript裡面使用不了mapState、mapGetters等方法,只能一個變數一個變數的去引用,這個要麻煩不少。不過使用vuex-class庫之後,寫法上也還算簡潔美觀

export default class modules extends Vue {
  @State login: boolean; // 對應this.$store.state.login
  @State headline: StoreState.headline[]; // 對應this.$store.state.headline

  private swiperOption: Object = {
    autoplay: true,
    loop: true,
    direction: "vertical"
  };

  logoClick(): void {
    alert("點我幹嘛");
  }
}
複製程式碼

專案截圖

Vue-TypeScript全面教程(附例項程式碼和一鍵構建工具) Vue-TypeScript全面教程(附例項程式碼和一鍵構建工具) Vue-TypeScript全面教程(附例項程式碼和一鍵構建工具)

總結

TypeScript還是非常值得學習和使用一個語言,還是有很多優點的

歡迎大家對我的專案提建議,覺得不錯的給個Star~

專案地址:github.com/SimonZhangI…

QQ交流群:323743292

Build Setup

# 安裝依賴
npm install

# 啟動專案
npm run dev

# 打包專案
npm run build
複製程式碼

相關文章