• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    使用VueCli3+TypeScript+Vuex一步步構建todoList的方法

    來源:懂視網 責編:小采 時間:2020-11-27 21:53:24
    文檔

    使用VueCli3+TypeScript+Vuex一步步構建todoList的方法

    使用VueCli3+TypeScript+Vuex一步步構建todoList的方法:前言 Vue3.x 即將來襲,使用 TypeScirpt 重構,TypeScript 將成為 vue 社區的標配,出于一名程序員的焦慮,決定現在 Vue2.6.x 踩一波坑。 vue 官方文檔已經簡略地對 typescript 的支持進行了介紹,我們使用 Vue Cli3 直接生成項目 創建項目
    推薦度:
    導讀使用VueCli3+TypeScript+Vuex一步步構建todoList的方法:前言 Vue3.x 即將來襲,使用 TypeScirpt 重構,TypeScript 將成為 vue 社區的標配,出于一名程序員的焦慮,決定現在 Vue2.6.x 踩一波坑。 vue 官方文檔已經簡略地對 typescript 的支持進行了介紹,我們使用 Vue Cli3 直接生成項目 創建項目

    前言

    Vue3.x 即將來襲,使用 TypeScirpt 重構,TypeScript 將成為 vue 社區的標配,出于一名程序員的焦慮,決定現在 Vue2.6.x 踩一波坑。

    vue 官方文檔已經簡略地對 typescript 的支持進行了介紹,我們使用 Vue Cli3 直接生成項目

    創建項目

    ❓為什么使用 Vue Cli3 構建項目

    官方維護,后續升級減少兼容性問題

    使用以下配置進行項目的生成:

  • Babel 對 Ts 進行轉譯
  • TSLint 對 TS 代碼進行規范,后續會使用 prettier 對項目進行編碼的統一
  • 默認安裝 Vuex 和 Router , Router 使用  history 模式
  • 使用 Jest 進行單元測試
  • ╭─~/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"
     ]
    }
    
  • target --- 被 tsc 編譯后生成 js 文件代碼風格
  • module --- 被 tsc 編譯后生成 js 文件的模塊風格
  • lib --- 原 ts 文件支持的代碼庫
  • 我們來看一下示例:

    // 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沒有指定默認注入的庫的列表。默認注入的庫為:

  • 針對于 target:ES5:DOM,ES5,ScriptHost
  • 針對于 target:ES6:DOM,ES6,DOM.Iterable,ScriptHost
  • 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

  • 勾選 tslintIntegration ,使 prittier 支持格式化 ts 文件
  • "editor.formatOnSave": true 保存時自動格式化
  • 也可以使用 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"
     style="margin-top:20px"
     >{{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 代碼的用法指出以下幾點:

    1. prop 建議寫成 xxx!: type 的形式,不然要寫成 xxx : type | undefined
    2. @Emit 可以不傳參數,emit 出去的事件名默認是修飾的函數名,但是當函數的命名規則為 camelCase 時需要注冊的函數名必須是 kebab-case
    3. @Emit 傳參是由修飾的函數 return value

    改造 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 需要注意以下幾點:

  • 對于 getters 、mutations 、actions 響應的 type 可以使用 command + 左鍵點擊 進入聲明文件查看,也可以不指定 type ,但是建議寫上
  • 對于 Payload 解構  tslint 報錯的,可以為 Payload 添加類型聲明
  • 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 的調用有以下幾點注意

  • @State 如果有分模塊,必須使用 state => state.xxx.xxx 的形式獲取state
  • @Action 中函數的聲明,形參必須和方法保持一致
  • 所有的代碼到此為止,使用 npm run serve 即可查看應用,保留原有 routes 文件,保持應用的健壯性。

    寫在最后

    1. 本文只是介紹了一個簡單構建 ts-vue 應用的例子,對于框架的健壯和可擴展性有需要慢慢考慮,比如 webpack 的配置,適應測試,生產等各種環境的區分,axois 的封裝,等等。
    2. 對于vue + ts 的配方,文章還有很多 vue 的特性沒有去兼容,比如 this.refs 的使用,比如 vue-property-decorator 其他特性的使用。
    3. 由于官方文檔對 ts 的介紹有限,所以以上代碼肯定有不足的地方,希望大家指正。

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    使用VueCli3+TypeScript+Vuex一步步構建todoList的方法

    使用VueCli3+TypeScript+Vuex一步步構建todoList的方法:前言 Vue3.x 即將來襲,使用 TypeScirpt 重構,TypeScript 將成為 vue 社區的標配,出于一名程序員的焦慮,決定現在 Vue2.6.x 踩一波坑。 vue 官方文檔已經簡略地對 typescript 的支持進行了介紹,我們使用 Vue Cli3 直接生成項目 創建項目
    推薦度:
    標簽: VUE todo list
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 日韩三级精品| 99精品热这里只有精品| 国产亚洲精品a在线无码| 久久精品三级视频| 久久精品草草草| 久久精品亚洲一区二区三区浴池| 国产精品热久久毛片| 精品国产综合成人亚洲区 | 国产精品久久久久久久久鸭| 亚洲一区二区三区国产精品| 久久久精品国产亚洲成人满18免费网站 | 99久久久精品| 久热这里只有精品视频6| 欧美精品人爱a欧美精品| 国产精品原创巨作?v网站| 免费欧美精品a在线| 福利姬在线精品观看| 久久精品国产亚洲av麻豆色欲| 中文无码久久精品| 一区二区国产精品| 亚洲午夜成人精品电影在线观看| 久久亚洲中文字幕精品一区| 国产在线精品一区二区高清不卡| 99久久伊人精品综合观看| 亚洲国产精品一区| 91精品免费久久久久久久久| 日本久久久精品中文字幕| 国产高清国产精品国产专区| 国产精品拍天天在线| 99精品人妻无码专区在线视频区| 国产成人精品无码免费看| 欧美精品中文字幕亚洲专区| 日韩人妻精品无码一区二区三区| 亚洲国产精品一区二区第一页免 | 精品国产一区二区三区免费| 国产成人精品免费视频大| 国产成人亚洲精品青草天美| 国产精品福利自产拍在线观看| 国产精品无码成人午夜电影| 久久99精品国产麻豆| 99精品久久精品一区二区|