標籤:

Vue + TypeScript踩坑(初始化項目)

  • 前言,最近公司新項目需要進行重構,框架選擇為Vue+TypeScript,記錄初始化中不完全踩坑指南

    1.項目改造

安裝所需的插件

npm install vue-property-decorator vuex-class --save npm install ts-loader typescript typescript-eslint-parser --save-dev

這些庫的作用,可以按需引入

- vue-property-decorator:在vue-class-component的基礎上優化{Emit, Inject, Model, Prop, Provide, Watch, Component}

- vuex-class:ts版的vuex插件

- ts-loader: webpack插件

- typescript: 必備插件

- typescript-eslint-parser: eslint解析ts插件

2.WebPack配置修改

webpac.conf中添加ts的解析module

extensions中添加ts結尾的文件

entry: { app: ./src/main.ts},// ....extensions: [.js, .vue, .json, .ts],// ....{ test: /.ts$/, loader: ts-loader, exclude: /node_modules/, options: { appendTsSuffixTo: [/.vue$/], }}

3.添加tsconfig.json、d.ts文件,修改eslint

修改eslint解析規則為ts

// ...parserOptions: { parser: typescript-eslint-parser},// ... plugins: [ vue, typescript],

在.eslintrc.js同級目錄創建tsconfig.json文件

{ "include": [ "src/*", "src/**/*" ], "exclude": [ "node_modules" ], "compilerOptions": { // types option has been previously configured "types": [ // add node as an option "node" ], // typeRoots option has been previously configured "typeRoots": [ // add path to @types "node_modules/@types" ], // 以嚴格模式解析 "strict": true, "strictPropertyInitialization": false, // 在.tsx文件里支持JSX "jsx": "preserve", // 使用的JSX工廠函數 "jsxFactory": "h", // 允許從沒有設置默認導出的模塊中默認導入 "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 }}

在src目錄下添加/typings/vue-shims.d.ts,聲明所有的.vue文件

declare module "*.vue" { import Vue from "vue"; export default Vue;}

4.對原有文件進行改造

/src/router/index.ts

import Vue, { AsyncComponent } from vueimport Router, { RouteConfig, Route, NavigationGuard } from vue-routerconst Home: AsyncComponent = (): any => import(@/views/Home/index.vue)Vue.use(Router)const routes: RouteConfig[] = [ { path: /, name: Home, component: Home }]const router: Router = new Router({ mode: history, base: /, routes})export default router

/src/store

index.ts

import Vue from vueimport Vuex, {ActionTree, MutationTree} from vueximport actions from ./actionsimport mutations from ./mutations;import getters from ./gettersVue.use(Vuex)interface State { token: string, login: Boolean,}let state: State = { token: token, login: false}export default new Vuex.Store({ state, getters, mutations, actions})

mutations.ts

import TYPES from ./typesimport { MutationTree } from vuexconst mutations: MutationTree<any> = { [TYPES.SET_TOKEN](state, token): void{ state.token = token }}export default mutations

actions.ts

import { ActionTree } from vueximport TYPES from ./typesconst actions: ActionTree<any, any> = { initToken({commit}, token: string) { commit(TYPES.SET_TOKEN, token) }}

export default actions

/src/main.ts

import Vue from vue;import App from ./App.vue;import store from ./storeimport router from ./router;Vue.config.productionTip = falsenew Vue({ el: #app, router, store, components: { App }, template: <App/>})

5.vue-property-decorator使用

vue-property-decorator基於vue-class-component封裝

提供了7種方法

import {Emit, Inject, Model, Prop, Provide, Watch, Componet}

<script lang="ts">import Vue from vueimport {Component, Prop, Emit} from vue-property-decoratorinterface List { title: string, imgSrc: string, url?: string}@Component({ name: HomeBlock, component: { // 這裡註冊組件 }})export default class HomeBlock extends Vue { @Prop({default: []}) dataList: List[] // 等同於 // props: { // dataList: { // default: [], // type: Array // } //} @Emit(jump) jumpRoute(url: string){ // ... } // 等同於 // jumpRoute(url) { // this.$emit(jump, url) // } @Watch(child) onChildChanged(val: string, oldVal: string) { } // 等同於 // watch: { // child: { // handler: onChildChanged, // immediate: false, // deep: false // }, // } mounted() { console.log(this.dataList) }}</script>

錯誤匯總

  1. typescript版本過新為3.1.x的情況會提示無法找到vue-loader,需要降級到2.8.x
  2. TS2564:Property xx has no initializer and in not definitely assigned in constructor

    在ts新版本中加入的,屬性初始化可能為undefined的情況需要考慮進去

    解決方案1,在定義的時候例如 url: string | undefined (不太清楚方法要怎麼定義,ts不太熟)

    解決方案2,在tsconfig的compilerOptions中 添加"strictPropertyInitialization": false,

推薦閱讀:

如何進一步熟悉甚至掌握Angular?
【認真臉】註解與裝飾器的點點滴滴
ThinkJS 3.0 如何實現對 TypeScript 的支持
現在 TypeScript 的生態如何?
基於 Immutable.js 實現撤銷重做功能

TAG:TypeScript | Vuejs |