Typescript 在前端圈已經逐漸普及,Vue 2.5.0 改進了類型聲明,使得對 TypeScript 更加友好 不過要想在項目中直接使用 TypeScript 仍然需要對項目進行一些改造 PS: 建議使用 Visual Studio Code 進行開發 一、安裝依賴 首先還是用 vue-cl ...
Typescript 在前端圈已經逐漸普及,Vue 2.5.0 改進了類型聲明,使得對 TypeScript 更加友好
不過要想在項目中直接使用 TypeScript 仍然需要對項目進行一些改造
PS: 建議使用 Visual Studio Code 進行開發
一、安裝依賴
首先還是用 vue-cli 生成項目
vue init webpack demo
然後安裝必要依賴項:typescript、ts-loader、vue-class-component
npm install typescript vue-class-component -D
npm install [email protected] -D
上面安裝 ts-loader 的時候,指定了版本 3.3.1
這是因為在寫這篇博客的時候(2018-03-14),在安裝 ts-loader 的最新版 4.0.1 的情況下,啟動項目會報錯
另外還有幾個庫可以按需引入:
tslint: 規範 ts 代碼,需要配合 tsllint-loader 使用,最好再加上 tslint-config-standard;
vue-property-decorator: vue-class-component 的擴展,添加了幾個結合 Vue 特性的裝飾器(@Emit,@Prop 等);
vuex-class: 在 vue-class-component 基礎上加強了對 vuex 的支持。
二、配置 Webpack
然後修改 ./build/webpack.base.conf.js 文件:
在 resolve.extension 中添加 ‘.ts’,使引入 ts 文件時不用寫 .ts 尾碼
{ test: /\.tsx?$/, loader: 'ts-loader', exclude: /node_modules/, options: { appendTsSuffixTo: [/\.vue$/] } }
在 module.rules 中添加 webpack 對 ts 文件的解析
三、其他配置
在項目根目錄下創建 tsconfig.json 文件:
// tsconfig.json { "compilerOptions": { // 與 Vue 的瀏覽器支持保持一致 "target": "es5", // 這可以對 `this` 上的數據屬性進行更嚴格的推斷 "strict": true, // 如果使用 webpack 2+ 或 rollup,可以利用 tree-shake: "module": "es2015", "moduleResolution": "node" } }
完整的 tsconfig.json 配置項可以參考官方文檔
在 ./src 目錄創建 vue-shim.d.ts 文件,讓 ts 識別 .vue 文件:
// vue-shim.d.ts declare module "*.vue" { import Vue from "vue"; export default Vue; }
四、文件改造
將 src 目錄下的所有 js 文件尾碼改為 .ts
然後將 webpack 配置文件 ./build/webpack.base.conf.js 中的入口 entry 修改為 main.ts
改造之後的 ts 文件不會識別 .vue 文件,所以在引入 .vue 文件的時候,需要手動添加 .vue 尾碼
在所有 .vue 文件中,都需要在 <script> 中添加 lang="ts" 標識
要讓 TypeScript 正確推斷 vue 組件選項中的類型,還需要引入 vue,並使用 Vue.extend 定義組件
至此基本改造已經完成,執行 npm run dev 就能正常啟動項目
五、基於類的 Vue 組件改造
上面改造 .vue 文件的時候,只是簡單的使用了 Vue.extend 方法,組件內部還是採用原生的 vue 寫法
這在實際開發的時候並不能良好的使用 typescript 特性,所以還需要利用 vue-class-component 繼續改造
首先在 tsconfig.json 中添加配置項,然後重啟項目
// 允許從沒有設置預設導出的模塊中預設導入 "allowSyntheticDefaultImports": true, // 啟用裝飾器 "experimentalDecorators": true
然後改造 .vue 文件的 <script> 部分,以 HelloWorld.vue 為例:
// HelloWorld.vue <script lang="ts"> import Vue from 'vue' import Component from 'vue-class-component' // @Component 修飾符註明瞭此類為一個 Vue 組件 @Component({}) export default class Hello extends Vue { msg: String = 'Welcome to Your Vue.js App' } </script>
組件內部不再採用 Vue 的格式,一開始也許不易接受,可以參考官方的遷移示例
// Vue 文件格式示範
<template> <div> <input v-model="msg"> <p>prop: {{propMessage}}</p> <p>msg: {{msg}}</p> <p>helloMsg: {{helloMsg}}</p> <p>computed msg: {{computedMsg}}</p> <button @click="greet">Greet</button> </div> </template> <script> import Vue from 'vue' import Component from 'vue-class-component' @Component({ props: { propMessage: String } }) export default class App extends Vue { // initial data msg = 123 // use prop values for initial data helloMsg = 'Hello, ' + this.propMessage // lifecycle hook mounted () { this.greet() } // computed get computedMsg () { return 'computed ' + this.msg } // method greet () { alert('greeting: ' + this.msg) } } </script>
六、使用TSlint 規範代碼
如果對代碼格式有著嚴格的要求,建議引入 tslint 來規範代碼,首先安裝以下依賴
npm init tslint tslint-loader tslint-config-standard -D
然後在 ./build/webpack.base.conf.js 的 module.rules 中添加規則
{ test: /\.ts$/, exclude: /node_modules/, enforce: 'pre', loader: 'tslint-loader' }
在項目根目錄創建配置文件 tslint.json
// tslint.json { "extends": "tslint-config-standard", "globals": { "require": true } }
這時已經可以啟動項目了,如果出現了這樣的警告
只需要在 main.ts 裡面,將實例化的 Vue 賦值給一個對象就好
只是這裡的 tslint 校驗規則是直接引入的 standard 規範,如果需要自定義
貼一篇網上找的 tslint.json 的配置項說明(來源:http://blog.csdn.net/zw52yany/article/details/78688837)
extends: 內設配置項名稱 rules: 規則 { //ts專用 adjacent-overload-signatures : true, // Enforces function overloads to be consecutive. ban-comma-operator:true, //禁止逗號運算符。 ban-type: [true, ["object","User {} instead."],["string"]] //禁止類型 member-access: [true , "no-public"||"check-accessor"|| "check-constructor" || "check-parameter-property" ] , //類成員必須聲明 private public .... member-order: [true, {order:....}], //類聲明排序 no-any: true,//不需使用any類型 no-empty-interface:true //禁止空介面 {} no-import-side-effect: [true, {"ignore-module": "(\\.html|\\.css)$"}], //禁止導入帶有副作用的語句 no-inferrable-types:[true, "ignore-params", "ignore-properties"], //不允許將變數或參數初始化為數字,字元串或布爾值的顯式類型聲明。 no-internal-module:true, //不允許內部模塊 no-magic-numbers: [true,1,2,3], //不允許在變數賦值之外使用常量數值。當沒有指定允許值列表時,預設允許-1,0和1 no-namespace: [ true,"allpw-declarations"], //不允許使用內部modules和命名空間 no-non-null-assertion: true , //不允許使用!尾碼操作符的非空斷言。 no-parameter-reassignment: true, //不允許重新分配參數 no-reference: true, // 禁止使用/// <reference path=> 導入 ,使用import代替 no-unnecessary-type-assertion: true, //如果類型斷言沒有改變表達式的類型就發出警告 no-var-requires: true, //不允許使用var module = require("module"),用 import foo = require('foo')導入 only-arrow-functions:[true,"allow-declarations","allow-named-functions"], //允許箭頭表達式,不需要傳統表達式 ; 允許獨立的函數聲明 ;允許表達,function foo() {}但不是function() {} prefer-for-of:true, //建議使用for(..of) promise-function-async: true, 要求非同步函數返回promise typedef: [true, "call-signature", "parameter", "member-variable-declaration"], //需要定義的類型存在 typedef-whitespace: true, //類型聲明的冒號之前是否需要空格 unified-signatures: true, //重載可以被統一聯合成一個 //function 專用 await-promise: true, //警告不是一個promise的await ban: [ true, "eval", {"name": "$", "message": "please don't"}, ["describe", "only"], {"name": ["it", "only"], "message": "don't focus tests"}, { "name": ["chai", "assert", "equal"], "message": "Use 'strictEqual' instead." }, {"name": ["*", "forEach"], "message": "Use a regular for loop instead."} ], curly: true, //for if do while 要有括弧 forin:true, //用for in 必須用if進行過濾 import-blacklist:true, //允許使用import require導入具體的模塊 label-postion: true, //允許在do/for/while/swith中使用label no-arg:true, //不允許使用 argument.callee no-bitwise:true, //不允許使用按位運算符 no-conditional-assignmen: true, //不允許在do-while/for/if/while判斷語句中使用賦值語句 no-console:true, //不能使用console no-construct: true, //不允許使用 String/Number/Boolean的構造函數 no-debugger: true, //不允許使用debugger no-duplicate-super: true, //構造函數兩次用super會發出警告 no-empty:true, //不允許空的塊 no-eval: true, //不允許使用eval no-floating-promises: true, //必須正確處理promise的返回函數 no-for-in-array: true, //不允許使用for in 遍曆數組 no-implicit-dependencies: true, //不允許在項目的package.json中導入未列為依賴項的模塊 no-inferred-empty-object-type: true, //不允許在函數和構造函數中使用{}的類型推斷 no-invalid-template-strings: true, //警告在非模板字元中使用${ no-invalid-this:true, //不允許在非class中使用 this關鍵字 no-misused-new: true, //禁止定義構造函數或new class no-null-keyword: true, //不允許使用null關鍵字 no-object-literal-type-assertion:true, //禁止objext出現在類型斷言表達式中 no-return-await:true, //不允許return await arrow-parens: true, //箭頭函數定義的參數需要括弧 }