91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2020-08-28 03:45:45 來源:腳本之家 閱讀:480 作者:三石流浪記 欄目:web開發

前言

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"
   
  >{{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 的介紹有限,所以以上代碼肯定有不足的地方,希望大家指正。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

泽普县| 辽源市| 辽宁省| 宁德市| 普陀区| 商城县| 衡南县| 鄄城县| 长葛市| 句容市| 赣榆县| 武陟县| 临澧县| 讷河市| 固阳县| 新乡市| 通渭县| 玉溪市| 江阴市| 横峰县| 白水县| 溧阳市| 兴国县| 图片| 贵德县| 浙江省| 镶黄旗| 大石桥市| 休宁县| 出国| 光山县| 高尔夫| 盐津县| 衡阳县| 祁门县| 佛冈县| 乌苏市| 邳州市| 应用必备| 通山县| 汝阳县|