俗話說一個項目,用代碼重寫十次,每次確定收益匪淺。後續還會持續重構ssr等。javascript
在vue裏使用ts,通常分爲兩種狀況:html
在最新的vue-cli 3.0中使用typescript,能夠說是很是方便了,由於添加了對ts的支持,用vue create 項目時,選第二項自定義配置添加對ts的支持就好了,另外別忘了把ts-lint語法檢測也加上。至於如何安裝vue-cli 3.0,去官方文檔看下就知道了。若是你想把這種配置做爲默認配置,文檔也給出了相應的配置以下,這樣你直接點第一個選項就會自動配置了。vue
被保存的 preset 將會存在用戶的 home 目錄下一個名爲
.vuerc
的 JSON 文件裏。若是你想要修改被保存的 preset / 選項,能夠編輯這個文件。java在項目建立的過程當中,你也會被提示選擇喜歡的包管理器或使用淘寶 npm 鏡像源以更快地安裝依賴。這些選擇也將會存入
~/.vuerc
。node
項目初始化完後,就能夠開箱即用了。看它的package.json文件,typescirpt 以及ts-loader幫你配置好了,還有vue-class-component,vue-property-decorator(點擊進入github地址查看文檔)這兩個添加vue對ts支持的插件也安裝好了,後者是前者的拓展版,通常選擇後面那個便可,tsconfig.json和.d.ts文件也配置好了,差很少例子也會幫你寫好了。固然例子所涉及的是遠遠不夠的,能夠去這兩個插件的github倉庫看下文檔,使用起來很是簡單,差很少是把之前vue那種黑盒子的寫法去掉了一層包裝加上了一層語法修飾器。詳細的配置就放到下面的vue-cli 3.0如下步驟中寫吧,也不用這麼累贅了,畢竟下面的須要手動去配置。webpack
首先初始化一個vue-cli 2.0的項目,文檔也給出了相應的方法:git
Vue CLI 3 和舊版使用了相同的
vue
命令,因此 Vue CLI 2 (vue-cli
) 被覆蓋了。若是你仍然須要使用舊版本的vue init
功能,你能夠全局安裝一個橋接工具:es6npm install -g @vue/cli-init # `vue init` 的運行效果將會跟 `vue-cli@2.x` 相同 vue init webpack my-project複製代碼
![]()
沒什麼特殊要求,一路回車就行了,初始完項目,打開package.json文件看下其依賴,是否是特別的多,在看下script下的dev命令,是基於webpack-dev-server,也就是仍是使用webpack加vue-loader就構成了vue-cli 2.0,因此插件須要一個一個裝,並自動配置在package.json裏。接下來就安裝各類依賴了。github
npm install typescript ts-loader --save-dev複製代碼
裝好以後,如何配置的教程,在ts-loader的npm包文檔和ts的官方文檔中寫的很詳細,下面我說說我本身重構項目所用到的吧!web
先要把ts-loader配置進webpack中,去webpack.config.js用vue-cli2.0也就是build文件夾裏找到webpack.base.conf.js:
resolve: {
extensions: ['.js', '.vue', '.json', '.ts'], // 這裏加入.ts文件的解析,若是使用了tsx,一併加上
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},複製代碼
而後添加ts-loader:
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.ts$/,
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/],
}
},複製代碼
因爲使用了語法檢測,因此還須要這個文件裏配置,再把入口文件改爲.ts,去src目錄下面把main.js改爲main.ts:
const createLintingRule = () => ({
test: /\.(js|vue|ts|tsx)$/, // 配置好ts,tsx的語法檢測支持
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})複製代碼
entry: {
app: './src/main.js' //改爲.ts
},複製代碼
接下來要把項目從新運行起來,就要去ts官方文檔看看了。同上講下項目所涉及到的。
TypeScript使用tsconfig.json
文件管理工程配置,因此須要在vue-cli第一層文件中加上這個文件。
文件的配置在ts官網項目配置也是作了很耐心的講解,下面我講下我所寫的吧。
// tsconfig.json
{
// 須要編譯的文件
"include": [
"src/**/*"
],
// 須要忽略編譯的文件
"exclude": [
"node_modules"
],
// 編譯器
"compilerOptions": {
// 包含的類型聲明文件路徑列表
"typeRoots": [
"node_modules/@types"
],
// 以嚴格模式解析
"strict": true,
// 容許從沒有設置默認導出的模塊中默認導入
"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
}
}
複製代碼
compilerOptions選項能夠按照它給那個列表按需求加入,好比添加一些代碼常量檢測之類的。
若是你的項目裏要使用一些npm包,第三方插件之類的,要爲它們在ts中建立申明文件,好比你使用了vue。則須要建立個vue.vue-shims.d.ts。
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}複製代碼
詳細使用能夠看下文檔。
而後把上面提到的vue-class-component,vue-property-decorator(點擊進入github地址查看文檔)這兩個插件裝好就能夠了,編寫規則在它們的github倉庫有說明,後者是前者的拓展版,通常選擇後面那個便可。
到這裏基本上就能瘋狂的擼ts代碼了,是否是感受很刺激,我的仍是推薦直接用vue-cli 3.0,先別說對ts的支持,整個項目看起來也是很是的乾淨。
下面我貼幾部分用ts寫的.vue文件做爲參考吧!詳細的還請各位大爺移步github倉庫查看。
<template>
<div class="hello">
<form id="loginFrom" method="get" action="#" @submit.prevent>
<div class="input" id="nkdiv">
...
<div id="login-btn">
<my-button
:disabled="button.disabled"
:value="button.value"
:btnStyle="button.btnStyle"
@click.native="login"
/>
</div>
<router-link to="/reset"><span class="button">忘記密碼?</span></router-link>
<router-link to="/register"><span class="button" id="register-btn">註冊新用戶</span></router-link>
</form>
</div>
</template>
<script lang='ts'>
import { Vue, Component } from "vue-property-decorator";
/**
* 這裏使用一個vuex-class的插件,其實它並不支持用class類去寫vuex,只是單純的作了下vuex對ts的支持而已,
* https://github.com/ktsn/vuex-class
* 因此我本身作了一下簡單的封裝,讓vuex擁有繼承屬性,可是在它github的下面有我真大佬寫的vuex-class.js,是
* 支持類的寫法的,歡迎你們去查看。https://github.com/lzxb/vuex-class.js
*/
// 這裏用的是裝飾器,分別對應vuex裏面那幾個map...的映射方法
import { Action, Mutation, Getter, namespace } from 'vuex-class';
import { Toast } from '../common/comjs';
// 表示鏈接的是login module。
const loginModule = namespace('login');
@Component({
components: {
// 這裏寫你引用的組件
},
/*因爲vue-property-decorator並無開放新增屬性的權限,因此你使用的與以前data,methods等同級
的屬性,只放到這裏面才能生效,這裏就至關與不用ts寫的那個export裏的環境,可是寫在這裏面,底下類
裏的this上有該屬性,可是拿不到*/
})
export default class login extends Vue {
// 表示映射的是login模塊下mutation裏的$isEmpty方法,其餘類推
@loginModule.Mutation('$isEmpty') $isEmpty: any;
@loginModule.Getter('_isEmpty') isEmpty: any;
@loginModule.Action('userLogin') userLogin: any;
@loginModule.Mutation('$assignParams') $assignParams :any;
@loginModule.Getter('_res') res: any;
nickname: string = '';
password: string = '';
button: MyButton.Button<MyButton.BtnStyle> = {
disabled: false,
value: '登錄',
btnStyle: {
width: '7.75rem',
height: '1.175rem',
fontSize: '0.5rem'
}
}
created () {
if (!this.$route.query.nickname) return;
this.nickname = this.$route.query.nickname
}
async login () {
let params = {
nickname: this.nickname,
password: this.password
}
this.$isEmpty(params);
if (this.isEmpty) return Toast('', '用戶名密碼不能爲空');
this.$assignParams(params);
this.button.disabled = true;
await this.userLogin();
setTimeout(() => {
this.button.disabled = false;
}, 1000);
if (this.res.data.token) {
...
}
Toast('', this.res.data);
}
}複製代碼
基於vue-cli3.0的github地址(項目正在重構中,歡迎fork參與,討論)
基於vue-cli2.0+ssr+pwa的github地址(使用了pwa離線緩存技術,歡迎start)
我的感受用ts以後,代碼風格很爽,代碼提示齊全,基本只要在那條鏈上,只要一路點點點就能夠寫完了,用js的話時常會寫錯函數名,變量名之類的,由於提示不多。能夠貼一段代碼出來看看,真的賊爽。下面是vuex類的寫法,特別推薦狼族大佬的vuex-class.js插件。
class View extends BaseLoaderData<ChatRoom.View.RequestParams, string> {
readonly namespaced: boolean = true;
public readonly state: ChatRoom.View.State = {
params: {
id: ''
},
res: { code: 0, data: '' },
requestStatus: 'unrequest'
};
async saveView(): Promise<this> {
this.$RequestStart();
const res = await this.api.saveView(this.state.params);
this.$RequestSuccess(res);
return this;
}
}
class ChatRoom extends VuexClass {
readonly namespaced: boolean = true;
articList: ArticList;
view: View;
modules: {
articList: ArticList;
view: View;
};
constructor() {
super(new chatroom());
this.articList = new ArticList();
this.view = new View(new chatroom());
this.modules = {
articList: this.articList,
view: this.view
};
}
}
export default ChatRoom;複製代碼
歡迎交流,若是以爲有幫助,歡迎start。