VUE 集成TypeScript之初步踩坑 (一)

爲何要集成TypeScript開發

如今2019年了,TypeScript愈來愈火,由於更多的人認識到了TypeScript的好處,一直寫一直爽。javascript

那用TypeScript開發項目後的優勢在哪裏尼?html

  • 減小bug
  • 下降維護成本
  • 接口可讀性好
  • 提升程序員的抽象能力

這些理由,應該有不少人會反對,你們都認爲用js寫項目,同樣也能夠實現上述理由,其餘人作不到那是寫的人不行,這個認知,我大部分也同意,可是咱們須要考慮現狀。前端

  • 一我的要保證每時每刻寫的代碼都很優質,其實很難的,好比說項目工期很趕,心情很差,這個時候寫的代碼也許過了三個月後,你本身都不認識了。
  • 利用一些強規定或者規範,約束你們不要寫垃圾代碼,好比說限定代碼的行數、一個函數的深度、多寫註釋、多寫文檔、增強review,前兩項也許能夠經過工具作到,後面的就須要花費比較多的人力,寫代碼的人累,review代碼的人也累,到最後可能又回到了原點。
  • 一個快速成型的團隊,或者跨部門合做時,每一個人每一個團隊都有本身的一套規範或者思想,這個時候溝通成本比較大,若是一塊兒開發項目,是很難保證項目的健壯性的,特別是js寫的代碼,自由度很是高,很是考驗一我的的水平。

這就是大部分團隊的現狀,項目越大,後期維護成本就越高,那爲啥TypeScript能夠下降這些問題發生的機率,或者縮小問題的規模尼。vue

TypeScript的優勢

  • 支持強類型,有默認的類型檢查,光這個就能夠減小不少沒必要要的bug,好比語法錯誤、類型轉換錯誤,寫的代碼更安全了。
  • 泛型支持,有了泛型,咱們寫共通代碼時,很輕鬆的就能夠知道對方須要什麼,既不用看文檔,也不須要問對方,很方便
  • 更好的和後端對接,如今後端通常都有一套接口定義規範,用專門的IDL語言來設計,前端按照這些規範生成相應的api調用代碼,若是是生成的js代碼,那很明顯不能完整的描述後端的強類型定義,TypeScript能夠很好的作到這一點
  • 一旦用了TypeScript,就意味你提供的接口,必需要給出明確的類型定義,在這種狀況下,須要更多主動的思考,時間長了,抽象能力天然而然就提升了。固然也能夠用any,可是若是都用any,那乾脆仍是用js好了,用啥TypeScript尼?

如何集成?

若是項目是全新的,有兩種方式: 一種是vue官方的教程,全部的配置都是基於vue-cli全家桶來作的,開箱就能用;一種是微軟出的教程,適合工程化有必定定製需求的團隊。java

如下是vue官方的教程node

  • 用【vue ui】命令時就建立項目,能夠直接選TypeScript。 react

    vue ui

  • 用【vue create my-project-name 】建立時命令行選擇 git

    vue create my-project-name

vue官方教程 cn.vuejs.org/v2/guide/ty…程序員

目前公司用的vue-cli搭建的項目,工程化文件都是vue默認提供的,微軟的就不介紹了,有興趣的能夠去看看github

微軟官方vue+ts教程: github.com/Microsoft/T…

若是項目已經存在,須要額外添加TypeScript的支持,vue官方也提供了支持,github.com/vuejs/vue-c…

vue add typescript
複製代碼

這個命令會自動把js項目轉換成ts,自動爲項目的package.json,加上相關的的依賴

package.json

記得把vue-class-component、vue-property-decorator升級下,默認的版本有點低

"vue-class-component": "^7.0.2",
    "vue-property-decorator": "^8.1.0",
複製代碼

升級完,建議修改下vue.config.js的配置

const path = require("path");
 configureWebpack: config => {
    config.resolve.modules.push(path.resolve(__dirname, "src"));
  }
複製代碼

這是爲了更好讀取src下的目錄,雖然vue.config.js 提供了src默認的alias => @,可是vue升級到vue3.0,在vs-code下,找組件關係依賴時,用@時,不是很方便,這是以前寫react時碰到的坑吧。

踩過的坑

1. Property 'store' does not exist on type 'VueConstructor'

由於在VueConstructor下是沒有定義store這個屬性,因此致使了這個錯誤

// main.ts
...
Vue.store = store;
...

複製代碼

既然知道了緣由,那麼修改下全局的VueConstructor這個就行了

// shims-vue.d.ts
import Vue, { ComponentOptions } from "vue";
import { Store } from "vuex";

declare module "vue/types/vue" {
  interface VueConstructor {
    store: Store<any>;
  }
}
複製代碼

再次編譯,發現已經沒有問題了。

2. 已有的項目作lint時報錯

若是是全新的項目按照官方生成的應該是沒有問題 ,可是已有的項目,由於歷史 緣由應該有不少lint規則和已有的lint規則不一致,致使報錯,要一個個 修改也是麻煩,並且有些是沒有辦法立馬修改的,好比說下面這種

<!-- eslint-disable max-lines -->
// 新的lint規則,不識別這種標識符。
····
// 路由規則
component: {
       render: h => (
            <keep-alive include="noticeIndex">
  // 沒有開啓jsx的功能,致使lint出錯
                <router-view />
           </keep-alive>
      )
}
複製代碼

還有就是一些歷史的js共通函數,這些均可能過不了新的lint規則,要一個個修正也麻煩,那怎麼解決尼?

有三種方式

  • 修改lint的規則,或者修改文件,一個個修改,看項目的複雜度,越古老的項目時間人力成本越大,可行性比較低
  • 直接廢棄@typescript-eslint/parser,沿用默認的lint規則,或者從新制定規則,這個若是對於lint規則比較熟悉的人,問題應該不大,不熟悉的就算了
  • 對已有的lint規則適配範圍進行修正,把規則限定在vue內,ts、tsx的用tslint作,目前咱們的lint規則是針對公司已有的業務 進行的定製,因此這一種方法比較適合咱們。(eslint、tslint、stylelint咱們定製了本身的庫)

直接上代碼

// .eslintrc
"overrides": [
    {
      "files": ["*.vue"],
      "parserOptions": {
        "ecmaFeatures": {
          "jsx": true
        }
      }
    }
  ]
// tsconfig.json
"exclude": ["node_modules", "dist", "src/main.ts"]
複製代碼

3. IDE沒法識別** import('xxx.vue') **

具體錯誤咱們看圖

IDE報錯

在run server時,控制檯也會報錯

控制檯報錯

雖然控制檯和IDE都報錯了,可是這個並不影響頁面的開發,只不過一堆的錯誤,放在控制檯確定很差看,Google了下發現也沒有特別好的解決方案,vue官方有一個issue,用// @ts-ignore 標識符忽略掉,只不過這個標識符每次只能忽略一行,若是在router組件內,有一堆的import,就很麻煩了。

@ts-ignore

vue官方issue: Typescript: IDE reports TS2307: Cannot find module error for Vue components imports

順着TypeScript的@ts-ignore線索,看看能不能一次性寫一個標識符,好比下面這樣

@ts-ignore-start
@ts-ignore-end

@ts-ignore-all

@ts-ignore-file
複製代碼

看着是否是很機智,哈哈,這是一個還在討論的issue,上面都是issue的建議,你們有時間去能夠跟下帖子,蠻有意思的。

TypeScript 官方issue: @ts-ignore for the block scope and imports

第一篇分享就到這。

有興趣的能夠繼續往下看

VUE 集成TypeScript之vue-router重構 (二)

相關文章
相關標籤/搜索