【架構師(第二十二篇)】編輯器開發之專案整體搭建

語言: CN / TW / HK

highlight: a11y-dark theme: smartblue


持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第2天,點選檢視活動詳情

這個階段更多的是編寫業務程式碼,除了編輯器之外沒什麼難度,需要記錄筆記的部分並不多,除非有特殊需要記錄的地 方,否則程式碼不會放在筆記裡。

TypeScript 技術補充

由於對 tsvue3 已經有了初步瞭解,本文就不對基礎記錄筆記,只補充一些自己不是很掌握的知識點。

👉👉 【初學者筆記】🐯年要掌握 Typescript

👉👉 【初學者筆記】整理的一些Vue3知識點

interface

```ts // 宣告函式型別 interface Foo { (x: number, y: number): number; }

// 可索引型別 interface RandomMap {

}

// 類陣列 , 可以通過陣列取值 , 但是不能呼叫方法 interface LikeArray {

}

// 函式新增屬性 interface FunctionWithProps { (x: number): number; name: string; }

// 定義介面型別 interface Animal { name: string; run(): void; }

// 實現介面 class cat implements Animal { name: string = "cat"; run() { this.name + "run"; } }

// 定義介面型別 interface Live { breathe(): void; }

// 實現多個型別的介面 class liveCat implements Animal, Live { name: string = "cat"; run() { this.name + "run"; } breathe() { this.name + "breathing"; } }

// 定義類的靜態型別 interface CatStatic { // 可以被 new 呼叫的建構函式 new (eyes: number, hands: number): void; }

// 類的陰陽兩面, 包含靜態型別和例項型別 const FooCat: CatStatic = class FooCat implements Cat { constructor(eyes: number, hands: number) {} name: string = "cat"; run() { this.name + "run"; } };

```

泛型

```ts // 泛型基礎 function foo(arg: T): T { return arg; }

// 交換 tuple 的位置 function swap(tuple: [T, K]): [K, T] { return [tuple[1], tuple[0]]; }

interface Person { name: string; age: number; }

interface Car { color: string; wheels: number; }

// 約定請求返回值結果 function getInfo(url: string): Promise { return fetch(url).then((resp) => resp.json()); }

// resp 是 Person 型別 getInfo('/getperson').then((resp) => {}); // resp 是 Car 型別 getInfo('/getcar').then((resp) => {});

// 傳入一個泛型, 把泛型中的屬性全部變為可選 type PersonPartial = Partial;

// 遍歷某個型別的鍵,返回由這些鍵組成的新的型別 type PersonKeys = keyof Person;

// lookup types 返回某個屬性的型別 type NameType = Person['name'];

// mapped types 遍歷 type Test = {

};

// 相當於複製了一份 Person 型別 type PersonCopy = {

};

// 實現了 Partial type PersonCopy = { p in PersonKeys?: Person[p]; };

// 泛型約束 interface IWithLength { length: number; } // 傳入的型別必須包含 length 屬性 function echoWithArr(arg: T): T { console.log(arg.length); return arg; }

// 條件型別關鍵字 // 判斷一個型別是否滿足另一個型別的約束 type NonType = T extends null | undefined ? never : T; ```

Vue3 技術補充

純函式 pure function

相同的輸入,永遠得到相同的輸出

js // 輸入 2 ,永遠輸出 4 function foo(a){ return a * 2 } // 輸入 2, 輸出不確定 function bar(a){ return a * Math.random() }

沒有副作用

  • 網路請求
  • DOM 操作
  • 訂閱資料來源
  • 寫入檔案系統
  • 獲取使用者輸入
  • ... ...

watchEffect

  • 初始化的時候會執行一次進行依賴的收集
  • 元件銷燬的時候會自動移除 watchEffect
  • 返回一個函式可以手動清除 watchEffect
  • 可以提供一個引數修改 watchEffect 的執行時機

js const count = ref(0); const stop = watchEffect(()=>{ console.log(count.value) }); stop(); watchEffect( ()=>{ console.log(count.value) }, { flush:"post" // 更新 dom 之後 } );

編輯器開發之專案整體搭建

將收穫什麼

  • 前端工具鏈的相關工具介紹

  • 腳手架工具的使用和對比

    • imooc-cli
    • vue-cli
    • vite
  • 編碼規範
    • ESLint
    • Prettier
    • 產出文件
  • 專案結構規範
    • 產出文件
  • Git 操作規範
    • 產出文件

建立專案

安裝 imooc-cli 腳手架,並生成專案。

js npm install -g @imooc-cli/core npm install -g cnpm imooc-cli --version imooc-cli init

Git Flow 標準操作流程

  • 根據需求,從 master 拉出分支
  • 開發階段,提交 commit
  • 開發完畢,發起 PR(pull request)
  • 程式碼評審
  • 部署,測試
  • mergemaster

兩大規則

  • 分支命名
    • feature 開頭代表新功能開發
    • hotfix 開頭代表 bug 修復
  • commit 資訊需要明確,杜絕 updatebugfix 等廢話,言之有物,言簡意賅的把一次 commit 說清楚。

專案基礎搭建

安裝第三方元件庫 ant-design-vue

通過 npm 安裝

js npm install ant-design-vue --save

引入 ```js // src\main.ts

import { createApp } from 'vue'; import App from './App.vue';

// 引入 Antd 元件庫 import Antd from 'ant-design-vue'; import 'ant-design-vue/dist/antd.css';

const app = createApp(App);

app.use(Antd).mount('#app'); ```

使用 js // App.vue <template> <a-button type="primary">Primary Button</a-button> </template>

vue-router

通過 npm 安裝

js npm install [email protected] --save

配置

```js // src\routes\index.ts

import { createRouter, createWebHistory } from 'vue-router'; import Home from '../views/Home.vue'; import Editor from '../views/Editor.vue'; import TemplateDetail from '../views/TemplateDetail.vue';

const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', name: 'home', component: Home, }, { path: '/editor', name: 'editor', component: Editor, }, { path: '/template/:id', name: 'template', component: TemplateDetail, }, ], }); export default router; ```

掛載到 vue 例項 ```js // src\main.ts

import router from './routes/index'; app.use(router); ```

vuex

通過 npm 安裝

js npm install [email protected] --save

配置

```js // src\store\index.ts

import { createStore } from 'vuex';

const store = createStore({ state: { count: 0 }, });

export default store; ```

掛載到 vue 例項 ```js // src\main.ts

import vuex from './routes/index'; app.use(vuex); ```

結合 ts

```js // src\store\index.ts

import { createStore } from 'vuex';

export interface GlobalStore { count: number; }

const store = createStore({ state: { count: 0 }, });

export default store; ```

vue 檔案中使用

```js // src\App.vue

import { useStore } from 'vuex' import { GlobalStore} from './store/index' import { computed } from 'vue';

const store = useStore() const count = computed(() => store.state.count) ```

使用 Module 分割 Vuex 模組

```ts // src\store\index.ts

import { createStore } from 'vuex'; import user from './user'; import template from './template'; import type { UserStore } from './user'; import type { TemplateStore } from './template';

export interface GlobalStore { user: UserStore; template: TemplateStore; }

const store = createStore({ modules: { user, template, }, });

export default store; ```

```ts // src\store\user.ts

import type { Module } from 'vuex'; import type { GlobalStore } from './index'; export interface UserProps { username: string; age: number; }

export type UserList = UserProps[];

export interface UserStore { userList: UserList; }

const userList: UserList = [ { username: 'foo', age: 18, }, { username: 'boo', age: 20, }, ];

const userStore: Module = { state: { userList: userList, }, getters: { getUserByName: (state) => (name: string) => { return state.userList.find((u) => u.username === name); }, }, };

export default userStore; ```

```ts // src\store\template.ts

import type { Module } from 'vuex'; import type { GlobalStore } from './index'; export interface TemplateProps { templateName: string; age: number; }

export type TemplateList = TemplateProps[];

export interface TemplateStore { templateList: TemplateList; }

const templateList: TemplateList = [ { templateName: 'foo', age: 18, }, { templateName: 'boo', age: 20, }, ];

const templateStore: Module = { state: { templateList: templateList, }, getters: { getTemplateByName: (state) => (name: string) => { return state.templateList.find((t) => t.templateName === name); }, }, };

export default templateStore; ```