1. 程式人生 > >如使用Typescript擼Vue(Vue2 + TS +TSX+CSS module)

如使用Typescript擼Vue(Vue2 + TS +TSX+CSS module)

install pla 完成 包裝 新建 無法 通過 lan asc

Vue對TS的支持一致不太好,連Vue作者尤大也自嘲真香壓錯了寶。期待Vue3.0會用TS重構且會有較大改進。不過目前有一些第三方的庫可以曲線優化對TS的支持。主要就介紹下過下面兩個庫來寫Vue。

總體體驗尚可,類型檢查,智能提示該有的都有,順滑中帶著一絲蹩腳。
如果要支持組件Props的類型檢查及智能提示,則必須放棄template通過render寫TSX, 總有種寫React的感覺。

介紹

kaorun343/vue-property-decorator?

vue-property-decorator 定義了很多的裝飾器,如 @prop,@component,@watch 等。已經相當齊全了,不多介紹了,而且此庫已經集成進了 vue-cli 3.0中,通過cli創建的項目也集成demo頁面。

wonderful-panda/vue-tsx-support?

vue-tsx-support 主要是用於支持再Vue的渲染函數中使用TSX,Vue本生是支持render JSX渲染的,在不涉及自定義Prop、事件時不使用該庫也可以。但如果component中有自定義prop,event,TS的類型檢查就會報錯。大致邏輯是在原有的Vue類上有包裝了一層,將屬性、事件、作用域插槽以泛型方式傳入接口定義,再將接口定義應用到TSX中。

CSS Module

Vue 默認是 scoped 方式引入css ,防止樣式汙染 ,通過vue模板使用也很方便。實際CSS 選擇器使用 scoped 這種方式效率低於 CSS Module,使用TSX渲染時樣式也只能通過CSS Module這樣方式引用。這裏再介紹個庫 classNames ,通過這個庫可以方便的組合樣式名。

創建項目

使用vue-cli 3.0 創建一個項目 , 必選 typescript Babel ,其他根據需要選。創建完成後已經引入了Vue 及 TS 相關包了,也包括上面提到的 vue-property-decorator。包含了一個實例代碼,npm install,npm run serve 已經可以跑起來了。

導入和配置

1. 安裝 vue-tsx-support 包

npm install vue-tsx-support --save

  

2. 導入TS聲明,有兩種方式

編輯tsconfig.js

  ...
"include": [
    "node_modules/vue-tsx-support/enable-check.d.ts",  
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ]
// 註意:將exclude內的 "node_modules" 刪掉,不然永遠也無法被引用到了
  ...

  

或者在main.js中 import

import "vue-tsx-support/enable-check";

3. 刪除根目錄下的 shims-tsx.d.ts ,否則會報重復定義的錯誤。

4. 根目錄新建 vue.config.js

module.exports = {
  css: {
    modules: true // 開啟CSS module
  },
  configureWebpack: {
    resolve: {
      extensions: [".js", ".vue", ".json", ".ts", ".tsx"] // 加入ts 和 tsx
    },
  },
  devServer: {
    port: 8800 // webpack-dev-server port
  }
};

  

創建視圖組件

來創建個按鈕組件:

 1 import { Component, Prop } from "vue-property-decorator";
 2 import * as tsx from "vue-tsx-support";
 3 
 4 export enum ButtonType {
 5   default = "default",
 6   primary = "primary"
 7 }
 8 
 9 export enum ButtonSize {
10   large = "large",
11   small = "small"
12 }
13 export interface IButtonProps {
14   type?: ButtonType;
15   size?: ButtonSize;
16   num: number;
17 }
18 
19 @Component
20 export default class Button extends tsx.Component<IButtonProps> {
21   @Prop() public type!: ButtonType;
22   @Prop() public size!: ButtonSize;
23   @Prop({ default: 0 }) public num!: number;
24 
25   protected render() {
26     return (
27       <div>
28         <p>id:{this.num}</p>
29         {this.type && <p>type:{this.type}</p>}
30         {this.size && <p>size:{this.size}</p>}
31       </div>
32     );
33   }
34 }

再創建Container 用TSX引用組件Button:

import { Component, Prop } from "vue-property-decorator";
import { Component as tsc } from "vue-tsx-support";
import Button, { ButtonType, ButtonSize } from "./button";

interface IContainerProps {
  name?: string;
}

@Component
export default class Container extends tsc<IContainerProps> {
  @Prop() public name!: string;

  protected render() {
    return (
      <div>
        <p>container Name:{this.name}</p>
        <p>{this.$slots.default}</p>
        <p>
          button:
          <Button num={9} type={ButtonType.primary} size={ButtonSize.large} />
        </p>
      </div>
    );
  }
}

此時即使在Container 的 Render 方法同樣會對 Props 進行類型檢查 ,而VS Code也有智能提示和自動引入,這體驗棒極了。

CSS Module 導入樣式

註意:使用CSS module 前 需要在vue.config.js 中配置 css.modules = true

註意:如要添加全局樣式可在 App.vue 中 @import 方式引用公用樣式,這樣就不會被CSS Module 加上後綴了。

然後加入TS定義

declare module "*.scss" {
  const content: any;
  export default content;
}

  

可以配合classnames庫,更方便的操作CSS類

classnames?www.npmjs.com

示例:

vaynewang/SampleCode/vue-tsx-sample/?

鏈接: 如使用Typescript擼Vue(Vue2 + TS +TSX+CSS module) - vaynewang的文章 - 知乎 https://zhuanlan.zhihu.com/p/58351868

如使用Typescript擼Vue(Vue2 + TS +TSX+CSS module)