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類
示例:
vaynewang/SampleCode/vue-tsx-sample/
