您好,登錄后才能下訂單哦!
前言
Vue3.x 即將來襲,使用 TypeScirpt 重構,TypeScript 將成為 vue 社區的標配,出于一名程序員的焦慮,決定現在 Vue2.6.x 踩一波坑。
vue 官方文檔已經簡略地對 typescript 的支持進行了介紹,我們使用 Vue Cli3 直接生成項目
創建項目
❓為什么使用 Vue Cli3 構建項目
官方維護,后續升級減少兼容性問題
使用以下配置進行項目的生成:
╭─~/otherEWokspace ╰─➤ vue create ts-vuex-demo Vue CLI v3.6.3 ┌───────────────────────────┐ │ Update available: 3.9.3 │ └───────────────────────────┘ ? Please pick a preset: Manually select features ? Check the features needed for your project: Babel, TS, Router, Vuex, CSS P re-processors, Linter, Unit ? Use class-style component syntax? Yes ? Use Babel alongside TypeScript for auto-detected polyfills? Yes ? Use history mode for router? (Requires proper server setup for index fallb ack in production) Yes ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are suppor ted by default): Sass/SCSS (with node-sass) ? Pick a linter / formatter config: TSLint ? Pick additional lint features: (Press <space> to select, <a> to toggle all , <i> to invert selection)Lint on save ? Pick a unit testing solution: Jest ? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In de dicated config files ? Save this as a preset for future projects? Yes ? Save preset as: ts-vue-demo
看一下新項目的層級目錄
╭─~/otherEWokspace/ts-vuex-demo ‹master› ╰─➤ tree -L 2 -I node_modules . ├── README.md ├── babel.config.js ├── jest.config.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── assets │ ├── components │ ├── main.ts │ ├── router.ts │ ├── shims-tsx.d.ts │ ├── shims-vue.d.ts │ ├── store.ts │ └── views ├── tests │ └── unit ├── tsconfig.json └── tslint.json
tsconfig.json
對 lib 、 target 、 module 進行解釋
{ "compilerOptions": { "target": "esnext", "module": "esnext", "strict": true, "jsx": "preserve", // 開啟對 jsx 的支持 "importHelpers": true, "moduleResolution": "node", "experimentalDecorators": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, "baseUrl": ".", "types": [ "webpack-env", "jest" ], "paths": { "@/*": [ "src/*" ] }, "lib": [ "esnext", "dom", "dom.iterable", "scripthost" ] }, "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx" ], "exclude": [ "node_modules" ] }
我們來看一下示例:
// index.ts export const Greeter = (name: string) => `Hello ${name}`;
"module": "commonjs", "target": "es5"
// index.js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Greeter = function (name) { return "Hello " + name; };
"module": "es2015", "target": "es5"
// index.js export var Greeter = function (name) { return "Hello " + name; };
"module": "es2015", "target": "es6"
// index.js export const Greeter = (name) => `Hello ${name}`;
"module": "commonjs", "target": "es6"
// index.js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Greeter = (name) => `Hello ${name}`;
如果lib沒有指定默認注入的庫的列表。默認注入的庫為:
tslint
類似于 eslint ,對 ts 代碼進行檢測。
vscode 需要安裝tslint 插件 ,并在 vscode 的用戶配置中加入以下配置,用來在保存時自動解決 ts 的錯誤。
// settings.json "editor.codeActionsOnSave": { "source.fixAll.tsLint": true }
❗️ vue cli3 已經安裝了tslint依賴
使用prettier 插件,對項目進行代碼風格的統一和規范
npm i tslint-config-prettier -D
添加 tslint.json extends 字段如下:
"extends": ["tslint:recommended", "tslint-config-prettier"]
設置 vscode
也可以使用 shift + option + f 進行格式化
在根目錄下添加 .prttierrc 文件 (應對 prittier 格式化 vue 文件中的 ts 文件時,沒辦法使用 tslint 規則進行格式化,需要對它單獨處理,以免 tslint 報錯)
{ "singleQuote": true }
shims-vue.d.ts
declare module "*.vue" { import Vue from "vue"; export default Vue; }
聲明所有以 .vue 結尾的文件,默認導入 vue ,默認導出 Vue,用以在項目中ts文件識別 .vue 結尾文件。
在 main.ts 中,引入一個 vue 組件必須以 .vue 結尾。
import Vue from 'vue'; import App from './App.vue'; import router from './router'; import store from './store'; Vue.config.productionTip = false; new Vue({ router, store, render: (h) => h(App), }).$mount('#app');
Vue class
vue-property-decorator
寫一個 todolist 組件順便來介紹 vue-property-decorator,為了方便頁面構建,使用 element-ui
element-ui 使用 ts 開發,默認有 .d.ts 的聲明文件
npm i element-ui
// main.ts import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI);
在 /src/compenents/ 新建 todoList.vue , 代碼如下:
<template> <div class="todo_list"> <el-card class="box-card"> <div slot="header"> <el-row :gutter="18"> <el-col :span="18"> <el-input v-model="todo" placeholder="請輸入內容" ></el-input> </el-col> <el-col :span="2"> <el-button type="primary" icon="el-icon-circle-plus-outline" @click="addItem" >add</el-button> </el-col> </el-row> </div> <div v-for="(item,index) in todoList" :key="item" class="text item" @click="removeItem(index)" >{{ item }}</div> </el-card> <label class="text" >{{todoLength}} records</label> </div> </template>
<script lang="ts"> import { Component, Prop, Vue, Emit } from 'vue-property-decorator'; @Component export default class HelloWorld extends Vue { public todo: string = ''; @Prop({ default: [] }) private readonly todoList!: string[]; get todoLength(): number { return this.todoList.length; } @Emit() private addItem(): string | undefined { if (this.todo) { return this.todo; } } @Emit('removeItem') private removeItem(index: number): number { return index; } } </script>
<!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang="scss"> .todo_list { display: flex; justify-content: center; flex-direction: column; align-items: center; .box-card { width: 480px; } .text { font-size: 14px; text-align: left; } .item { margin-bottom: 18px; } } </style>
對 ts 代碼的用法指出以下幾點:
改造 Home.vue 如下:
<template> <div class="home"> <todoList :todoList="[]" @add-item="addTodoList" @removeItem="addTodoLisItem" /> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; import todoList from '@/components/todoList.vue'; // @ is an alias to /src import { State, Getter, Action } from 'vuex-class'; @Component({ components: { todoList } }) export default class Home extends Vue { public addTodoList(val: string) { console.log(val); } private created() { console.log('i add life cycle funciton -- created'); } private addTodoLisItem(index: number) { console.log(index); } } </script>
Vuex
有關 ts 中的 vuex 的寫法要從vuex-class 說起,在 官方的 vue-property-decorator 中也推薦使用該庫。
npm i vuex-class
在 src 文件夾中新建 store 文件夾, 在 store 新建 index.ts,todoList.ts
// index.ts import Vue from 'vue'; import Vuex from 'vuex'; import todolist from './todoList'; Vue.use(Vuex); export default new Vuex.Store({ modules: { todolist } });
// todoList.ts import { Commit, Dispatch, GetterTree, ActionTree, MutationTree } from 'vuex'; const ADD_TODOLIST = 'ADD_TODOLIST'; const REMOVE_ITEM = 'REMOVE_ITEM'; export interface RootState { version: string; } interface Payload { [propName: string]: any; } interface TodoListType { todoList: string[]; } interface Context { commit: Commit; dispatch: Dispatch; } const dataSource: TodoListType = { todoList: [] }; const getters: GetterTree<TodoListType, RootState> = { getTodoList(state: TodoListType): string[] { return state.todoList; } }; const mutations: MutationTree<TodoListType> = { ADD_TODOLIST: (state: TodoListType, item: string) => { console.log(item); state.todoList.push(item); }, REMOVE_ITEM: (state: TodoListType, removeIndex: number) => { state.todoList = state.todoList.filter((item: string, index: number) => { return removeIndex !== index; }); } }; const actions: ActionTree<TodoListType, RootState> = { addList: async ({ commit }: Context, item: string) => { await Promise.resolve( setTimeout(() => { commit(ADD_TODOLIST, item); }, 100) ); }, removeItem: async ({ commit }: Context, { index }: Payload) => { await Promise.resolve( setTimeout(() => { commit(REMOVE_ITEM, index); }, 100) ); } }; export default { namespaced: true, state: dataSource, getters, mutations, actions };
刪除原來與 main.ts 同級的 store.ts
對 todoList.ts 需要注意以下幾點:
interface Payload { [propName: string]: any; }
代碼中的 dataSource 本意為 state ,但是不能用 state 命名,tslint 會和形參 state 沖突
改造 /views/Home.vue 如下:
<template> <div class="home"> <todoList :todoList="todoList" @add-item="addTodoList" @removeItem="addTodoLisItem" /> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; import todoList from '@/components/todoList.vue'; // @ is an alias to /src import { State, Getter, Action } from 'vuex-class'; @Component({ components: { todoList } }) export default class Home extends Vue { @State(state => state.todolist.todoList) private todoList!: string[]; @Action('todolist/addList') private addList!: (val: string) => void; @Action('todolist/removeItem') private removeItem!: (index: number) => void; public addTodoList(val: string) { console.log(val); this.addList(val); } private created() { console.log('i add life cycle funciton -- created'); } private addTodoLisItem(index: number) { this.removeItem(index); } } </script>
有關 vuex-class 的調用有以下幾點注意
所有的代碼到此為止,使用 npm run serve 即可查看應用,保留原有 routes 文件,保持應用的健壯性。
寫在最后
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。