摘要:Vue 3已經釋出有一段時間了,到底有哪些新特性值得關注,如何用它建構企業級前端項目,怎樣快速上手Vue 3?本篇文章将對此進行詳細講解。
前言
工欲善其事,必先利其器 --《論語》
在如今被三大架構支配的前端領域,已經很少有人不知道 Vue 了。2014 年,前 Google 工程師尤雨溪釋出了所謂的漸進式(Progressive)前端應用架構 Vue,其簡化的模版綁定群組件化思想給當時還是 jQuery 時代的前端領域産生了積極而深遠的影響。Vue 的誕生,造福了那些不習慣 TS 或 JSX 文法的前端開發者。而且,Vue 較低的學習門檻,也讓初學者非常容易上手。這也是為什麼 Vue 能在短時間内迅速推廣的重要原因。從 State of JS 的調查中可以看到,Vue 的知名度接近 100%,而且整體使用者滿意度也比較高。

Vue 既強大又易學,這是不是意味着 Vue 是一個完美架構呢?很遺憾,答案是否定的。雖然 Vue 的上手門檻不高,靈活易用,但是這種優勢同時也成為了一把雙刃劍,為建構大型項目帶來了一定的局限性。很多用 Vue 2 開發過大型項目的前端工程師對 Vue 是又愛又恨。不過,随着 Vue 3 的釋出,這些開發大型項目時凸顯出來的劣勢得到了有效解決,這讓 Vue 架構變得非常全能,真正具備了跟 “前端架構一哥” React 一争高下的潛力。Vue 3 究竟帶來了什麼重要的新特性呢?本篇文章将對此進行詳細介紹。
Vue 概覽
Vue 是前 Google 工程師尤雨溪于 2013 年開發、2014 年釋出的前端架構。關于 Vue 的具體定義,這裡摘抄 Vue 官網裡的介紹。
Vue (讀音 /vjuː/,類似于 view) 是一套用于建構使用者界面的漸進式架構。與其它大型架構不同的是,Vue 被設計為可以自底向上逐層應用。Vue 的核心庫隻關注視圖層,不僅易于上手,還便于與第三方庫或既有項目整合。另一方面,當與現代化的工具鍊以及各種支援類庫結合使用時,Vue 也完全能夠為複雜的單頁應用提供驅動。
漸進式架構
很多人可能不了解漸進式架構(Progressive Framework)的含義。這裡簡單解釋一下。漸進主要是針對項目開發過程來說的。傳統的軟體項目開發通常是瀑布流式(Waterfall)的,也就是說,軟體設計開發任務通常有明确的時間線,任務與任務之間有明确的依賴關系,這意味着項目的不确定性容忍度(Intolerance to Uncertainty)比較低。這種開發模式在現代日趨複雜而快速變化的商業情景已經顯得比較過時了,因為很多時候需求是不确定的,這會給項目帶來很大的風險。
而漸進式架構或漸進式開發模式則可以解決這種問題。以 Vue 為例:項目開始時,功能要求簡單,可以用一些比較簡單的 API;當項目逐漸開發,一些公共元件需要抽象出來,是以用到了 Vue 的元件化功能;當項目變得非常大的時候,可以引用 Vue Router 或者 Vuex 等子產品來進一步工程化前端系統。看到了麼,這樣一來,開發流程變得非常靈活,不用提前設計整個系統,隻用按需開發,是以可以快速開發産品原型以及擴充到生産系統。
架構特性
Vue 是利用模版文法來渲染頁面的,這也稱做聲明式渲染。Vue 好上手的重要原因也是因為這個,因為它符合了前端開發者的習慣。例如下面這個例子。
<div id="app">
{{message}}
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
可以看到,el 指定 Vue 執行個體綁定的元素,data 中的 message 與 DOM 元素的内容進行綁定。隻需要操控 JS 中的資料,HTML 内容也會随之改變。
另外,Vue 将 HTML、CSS、JS 全部整合在同一個檔案 .vue 中,以元件化應用建構的方式來組織代碼,從文法特性上鼓勵 “高内聚、低耦合” 的設計理念,讓代碼組織變得更加合理,提升了可讀性與邏輯性。下面是一個官方網站給出的基礎 .vue 檔案例子。
<template>
<p>{{ greeting }} World!</p>
</template>
<script>
module.exports = {
data: function () {
return {
greeting: 'Hello'
}
}
}
</script>
<style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>
元件的骨架(HTML)、樣式(CSS)和資料或操作(JS)都在同一個地方,開發者需要思考如何将整個系統拆分成更小的子子產品,或者元件。這對于建構大型項目是非常有幫助的。
其實,除了上述兩個特點,Vue 還有很多其他的實用特性,但限于篇幅的原因,我們這裡不詳細解釋了。感興趣的讀者可以去[官方網站深入了解。
架構缺點
沒有什麼東西是完美的,Vue 同樣如此。當 Vue 的知名度和使用者量不斷增加時,一些前端開發者開始抱怨 Vue 的靈活性太高導緻建構大型項目時缺少限制,進而容易産生大量 bug。甚至使用 Vue 生态圈裡的狀态管理系統 Vuex 也無法有效解決。關于 Vue 是否适合大型項目的問題,網上有不少争論,甚至尤大學人都親自上知乎參與了讨論(吃瓜傳送門)。
客觀來講,Vue 雖然具有較低的上手門檻,但這并不意味着 Vue 不适合開發大型項目。然而,我們也必須承認大型項目通常要求較高的穩定性和可維護性,而 Vue 架構較高的靈活性以及缺少足夠的限制讓其容易被經驗不足的前端開發者所濫用,進而産生臭不可聞的、難以直視的 “屎山” 代碼。其實,代碼可維護性并不強制要求較低的靈活性與自由度,隻是這種自由可能會對項目的整體穩定帶來風險。
Vue 作者尤雨溪其實很早就注意到這個問題,是以才會打算從底層重構 Vue,讓其更好的支援 TypeScript。這就是 2020 年 9 月釋出的 Vue 3。
Vue 3 新特性
Vue 3 有很多實用的新特性,包括TS 支援、組合式 API 以及 Teleport 等等。本文不是關于 Vue 3 的參考文,是以不會介紹其中全部的新特性,我們隻會關注其中比較重要的特性,尤其是能加強代碼限制的 TypeScript(簡稱 TS)。
TS 支援
技術上來說,TS 支援并不是 Vue 3 的新特性,因為 Vue 2 版本就已經能夠支援 TS 了。但 Vue 2 版本的 TS 支援,是通過 vue-class-component 這種蹩腳的裝飾器方式來實作的。筆者對 “蹩腳” 這個評價深有體會,因為筆者曾經遷移過 Vue 2 版本的生産環境項目,最後發現收益并不高:文法有很大的不同,花了大量時間來重構,發現隻提升了一些代碼的規範性,但是代碼整體變得更臃腫了,可讀性變得更差。
而在 Vue 3 中,TS 是原生支援的,因為 Vue 3 本身就是用 TS 編寫的,TS 成為了 Vue 3 中的 “一等公民”。TS 支援在我看來是 Vue 3 中最重要的特性,特别是對建構大型前端項目來說。為什麼說它重要?因為 TS 有效的解決了前端工程化和規模化的問題,它在代碼規範和設計模式上極大的提高代碼品質,進而增強系統的可靠性、穩定性和可維護性。關于 TS 的重要性,筆者在該公衆号前一篇文章《為什麼說 TypeScript 是開發大型前端項目的必備語言》已經做了詳細介紹,感興趣的讀者可以繼續深入閱讀一下。
Vue 3 定義了很多 TS 接口(Interface)和類型(Type),幫助開發者定義和限制各個變量、方法、類的種類。下面就是一個非常基礎的例子。
import { defineComponent } from 'vue'
// 定義 Book 接口
interface Book {
title: string
author: string
year: number
}
// defineComponent 定義元件類型
const Component = defineComponent({
data() {
return {
book: {
title: 'Vue 3 Guide',
author: 'Vue Team',
year: 2020
} as Book // as Book 是一個斷言
}
}
})
上述代碼通過 defineComponent 定義了元件類型,而在 data 裡定義了内部變量 book,這個是通過接口 Book 來定義的。是以,其他元件在引用該元件時,就能夠自動推斷出該元件的類型、内部變量類型,等等。如果引用方與被引用方的任何一個接口、變量類型不一緻,TS 就會抛錯,讓你可以提前規避很多錯誤。
雖然 Vue 3 在傳統定義 Vue 執行個體方式中(Options API)能夠很好的支援 TS,但是我們更推薦用 TS 配合另一種新的方式來定義 Vue 執行個體,也就是接下來要介紹的組合式 API(Compositional API)。
組合式 API
組合式 API 的誕生是來自于大型項目中無法優雅而有效地複用大量元件的問題。如果你已經了解 Vue,你或許應該知道之前版本的 Vue 執行個體中包含很多固定的 API,包括 data、computed、methods 等。這種定義方式有個比較突出的問題:它将 Vue 執行個體中的功能按照類型的不同分别固定在不同的 API 中,而沒有根據實際的功能來劃分,這将導緻一個複雜元件中的代碼變得非常散亂,就像如下這張圖一樣。
在這個 “科學怪人” 式的傳統元件中,同一種顔色的代碼負責同一種功能,但它們卻根據不同類型分散在不同的區域,這将導緻初次接觸該元件的開發人員難以快速了解整個元件的功能和邏輯。而組合式 API 則允許開發者将元件中相關的功能和變量聚合在一個地方,在外部按需引用,進而避免了傳統方式的邏輯散亂問題。
在 Vue 3 的組合式 API 中,所有功能和邏輯隻需要定義在 setup 這個方法中。setup 接受屬性 props 和上下文 context 兩個參數,并在方法内部定義所需要的變量和方法,傳回值是包含公共變量和方法的對象,它們可以供其他元件和子產品使用。傳統 Vue 執行個體的大部分 API,例如 data、computed、methods 等,都可以在 setup 中定義。下面是官網關于組合式 API 的例子。
// src/components/UserRepositories.vue
import { toRefs } from 'vue'
import useUserRepositories from '@/composables/useUserRepositories'
import useRepositoryNameSearch from '@/composables/useRepositoryNameSearch'
import useRepositoryFilters from '@/composables/useRepositoryFilters'
export default {
// 引用子元件
components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
// 屬性
props: {
user: { type: String }
},
setup(props) {
// 解構屬性,如果直接在 setup 中引用,必須要加 toRefs
const { user } = toRefs(props)
// 擷取 repository 相關公共方法,在其他子產品中定義
const { repositories, getUserRepositories } = useUserRepositories(user)
// 搜尋 repository 相關公共方法,在其他子產品中定義
const {
searchQuery,
repositoriesMatchingSearchQuery
} = useRepositoryNameSearch(repositories)
// 過濾 repository 相關公共方法,在其他子產品中定義
const {
filters,
updateFilters,
filteredRepositories
} = useRepositoryFilters(repositoriesMatchingSearchQuery)
return {
// 因為我們并不關心未經過濾的倉庫
// 我們可以在 `repositories` 名稱下暴露過濾後的結果
repositories: filteredRepositories,
getUserRepositories,
searchQuery,
filters,
updateFilters
}
}
}
在這個例子中,該元件需要的變量或方法全部在其他子產品定義了,并通過 useXXX 的函數暴露給外部元件,而且還可以被其他元件重複使用。這樣看上去是不是更清爽了呢?
你可能會思考怎麼寫 useXXX 這種函數。其實非常簡單,下面就是一個例子。
// src/composables/useUserRepositories.js
import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted, watch } from 'vue'
export default function useUserRepositories(user) {
// 内部清單變量
const repositories = ref([])
// 擷取清單方法
const getUserRepositories = async () => {
repositories.value = await fetchUserRepositories(user.value)
}
// 初次擷取清單,挂載後執行,相當于傳統元件中的 mounted
onMounted(getUserRepositories)
// 監聽 user 并根據變化來擷取最新清單,相當于傳統元件中的 watch
watch(user, getUserRepositories)
// 傳回公共變量和方法
return {
repositories,
getUserRepositories
}
}
傳統元件中的一些 API,例如 mounted 和 watch,已經成為了按需引用的函數,功能跟之前一模一樣。而之前的 data、computed、methods 變成 setup 函數中的内部變量,并根據是否傳回來決定是否暴露給外部。
需要注意的是,Vue 3 中引入了響應式 API 的概念,之前的變量都需要根據需要用不同的響應式 API 來定義。其具體原理不深入介紹了,感興趣的讀者可以到官方文檔繼續深入學習。
其他新特性
Vue 3 還有其他一些新特性,限于篇幅原因就不詳細介紹了。這裡隻列出一些比較實用的新特性及其簡單介紹。
- Teleport - 适用于 Modal、Popover 等需要挂載在全局 DOM 元素中的元件
- 片段 - 元件支援多個根節點
- 觸發元件選項 - 關于事件的相關 API 變更
全部變更清單,請參考官方文檔(英文)。
大型項目實戰
前面介紹了這麼多理論知識,對于前端工程師來說可能還不夠,要在工作中讓所學知識發揮作用,還必須要用到項目實踐中,特别是大型項目。是以,這個小節将着重介紹如何用 Vue 3 來建構企業級項目。本小節将用筆者的一個 Github 倉庫 作為示範,講解如何用 Vue 3 建構大型前端項目。
這個倉庫是筆者的一個開源項目 Crawlab 的下一個版本 v0.6 的前端部分。它目前還處于開發中的狀态,并不是成品;不過代碼組織結構已經成型,作為示範來說已經足夠。之前的版本是用 Vue 2 寫的,用的是傳統 Vue API。這個 Vue 3 版本将使用 TS 群組合式 API 來完成重構和遷移,然後在此基礎上加入更多實用的功能。對該前端項目感興趣的讀者可以通路該 Github 倉庫了解代碼細節,同時也非常歡迎大家跟我讨論任何相關問題,包括不合理或需要優化的地方。
倉庫位址: https://github.com/crawlab-team/crawlab-frontend
項目結構
該項目的代碼組織結構如下。其中忽略了一些不重要的檔案或目錄。
.
├── public // 公共資源
├── src // 源代碼目錄
│ ├── assets // 靜态資源
│ ├── components // 元件
│ ├── constants // 常量
│ ├── i18n // 國際化
│ ├── interfaces // TS 類型聲明
│ ├── layouts // 布局
│ ├── router // 路由
│ ├── services // 服務
│ ├── store // 狀态管理
│ ├── styles // CSS/SCSS 樣式
│ ├── test // 測試
│ ├── utils // 輔助方法
│ ├── views // 頁面
│ ├── App.vue // 主應用
│ ├── main.ts // 主入口
│ └── shims-vue.d.ts // 相容 Vue 聲明檔案
├── .eslintrc.js // ESLint 配置檔案
├── .eslintignore // ESLint Ignore 檔案
├── babel.config.js // Babel 編譯配置檔案
├── jest.config.ts // 單元測試配置檔案
├── package.json // 項目配置檔案
└── tsconfig.json // TS 配置檔案
可以看到,這個前端項目有非常多的子子產品,包括元件、布局、狀态管理等等。在 src 目錄中有十多個子目錄,也就是十多個子產品,這還不包括各個子產品下的子目錄,是以子產品非常多,結構也非常複雜。這是一個典型的大型前端項目的項目結構。企業級項目,例如 ERP、CRM、ITSM 或其他背景管理系統,大部分都有很多功能子產品以及清晰的項目結構。這些子產品各司其職,互相協作,共同構成了整個前端應用。
其實這種項目結構并不隻适用于 Vue,其他架構的項目例如 React、Angular 都可以是類似的。
TS 類型聲明
TS 幾乎是現代大型前端項目的标配,其強大的類型系統可以規避大型項目中很多常見的錯誤和風險。是以,我們在這個前端項目中也采用了 TS 來做類型系統。
在前面的項目結構中,我們在 src/interfaces 目錄中聲明 TS 類型。類型聲明檔案用 <name>.d.ts 來表示,name 表示是跟這個子產品相關的類型聲明。例如,在 src/interfaces/layout/TabsView.d.ts 這個檔案中,我們定義了跟 TabsView 這個布局元件相關的類型,内容如下。
interface Tab {
id?: number;
path: string;
dragging?: boolean;
}
更複雜的例子是狀态管理的類型聲明檔案,例如 src/interfaces/store/spider.d.ts,這是 Vue 中狀态管理庫 Vuex 的其中一個子產品聲明檔案,内容如下。
// 引入第三方類型
import {GetterTree, Module, MutationTree} from 'vuex';
// 如果引入了第三方類型,需要顯式做全局聲明
declare global {
// 繼承 Vuex 的基礎類型 Module
interface SpiderStoreModule extends Module<SpiderStoreState, RootStoreState> {
getters: SpiderStoreGetters;
mutations: SpiderStoreMutations;
}
// 狀态類型
// NavItem 為自定義類型
interface SpiderStoreState {
sidebarCollapsed: boolean;
actionsCollapsed: boolean;
tabs: NavItem[];
}
// Getters
// StoreGetter 為自定義基礎類型
interface SpiderStoreGetters extends GetterTree<SpiderStoreState, RootStoreState> {
tabName: StoreGetter<SpiderStoreState, RootStoreState, SpiderTabName>;
}
// Mutations
// StoreMutation 為自定義基礎類型
interface SpiderStoreMutations extends MutationTree<SpiderStoreState> {
setSidebarCollapsed: StoreMutation<SpiderStoreState, boolean>;
setActionsCollapsed: StoreMutation<SpiderStoreState, boolean>;
}
}
其中,尖括号 <...> 裡的内容是 TS 中的泛型,這能大幅度提高類型的通用性,通常用作基礎類型。
下面是引用 TS 類型的例子 src/store/modules/spider.ts。
import router from '@/router';
export default {
namespaced: true,
state: {
sidebarCollapsed: false,
actionsCollapsed: false,
tabs: [
{id: 'overview', title: 'Overview'},
{id: 'files', title: 'Files'},
{id: 'tasks', title: 'Tasks'},
{id: 'settings', title: 'Settings'},
],
},
getters: {
tabName: () => {
const arr = router.currentRoute.value.path.split('/');
if (arr.length < 3) return null;
return arr[3];
}
},
mutations: {
setSidebarCollapsed: (state: SpiderStoreState, value: boolean) => {
state.sidebarCollapsed = value;
},
setActionsCollapsed: (state: SpiderStoreState, value: boolean) => {
state.actionsCollapsed = value;
},
},
actions: {}
} as SpiderStoreModule;
這裡用了 as SpiderStoreModule 的斷言,TS 靜态檢測器會自動将 SpiderStoreModule 中的元素推斷出來,并與實際的變量做比對。如果出現了不一緻,就會抛錯。
元件化
元件化是現代前端項目的主流,在 Vue 3 中也不例外。Vue 3 的元件化跟 Vue 2 比較類似,都是用 Vue 執行個體來定義各類元件。在這個前端項目中,元件被分類成了不同種類,同一種類的放在一個檔案夾中,如下。
.
└── src
└── components
├── button // 按鈕
├── context-menu // 右鍵菜單
├── drag // 拖拽
├── file // 檔案
├── icon // Icon
├── nav // 導航
├── table // 表格
└── ...
元件檔案為 <ComponentName>.vue 定義,如下是其中一個關于右鍵菜單的例子 src/components/context-menu/ContextMenu.vue。
<template>
<el-popover
:placement="placement"
:show-arrow="false"
:visible="visible"
popper-class="context-menu"
trigger="manual"
>
<template #default>
<slot name="default"></slot>
</template>
<template #reference>
<div v-click-outside="onClickOutside">
<slot name="reference"></slot>
</div>
</template>
</el-popover>
</template>
<script lang="ts">
import {defineComponent} from 'vue';
import {ClickOutside} from 'element-plus/lib/directives';
// 定義屬性
export const contextMenuDefaultProps = {
visible: {
type: Boolean,
default: false,
},
placement: {
type: String,
default: 'right-start',
},
};
// 定義觸發事件
export const contextMenuDefaultEmits = [
'hide',
];
// 定義元件
export default defineComponent({
// 元件名稱
name: 'ContextMenu',
// 引用外部指令
directives: {
ClickOutside,
},
// 觸發事件
emits: contextMenuDefaultEmits,
// 屬性
props: contextMenuDefaultProps,
// 組合式 API
setup(props, {emit}) {
// 點選事件函數
const onClickOutside = () => {
emit('hide');
};
// 傳回公共對象
return {
onClickOutside,
};
},
});
</script>
你可能會有疑慮:這裡似乎沒用到 TS 中的類型系統啊。其實這隻是一個非常簡單的元件,包含完整 TS 特性的元件例子可以參考下面這個元件。
src/file/FileEditor.vue
: https://github.com/crawlab-team/crawlab-frontend/blob/main/src/components/file/FileEditor.vue
其他
限于篇幅原因,本文不會詳細介紹其他所有子產品。這裡隻簡單列舉一下。
- UI 架構(UI Framework)- 用了 Element+ 作為 UI 架構
- 布局(Layouts)- 基礎布局 BasicLayout 定義了頂部、側邊欄、底部等元素
- 狀态管理(State Management)- 相當于全局資料管理系統
- 路由(Routing)- 頁面路由配置
- 國際化(Internationalization)- 多語言配置
- 樣式(Styles)- 利用 SCSS 定義了全局樣式以及樣式變量等
- 服務(Services)- 包括與後端 API 的互動函數
- 常量(Constants)
- 輔助方法(Utilities)
如何學習 Vue 3
關于 Vue 3 的學習途徑,其實首先應該是閱讀官方文檔,了解 Vue 3 的基礎概念、高階原理以及如何工程化等等。作者尤雨溪已經在文檔中非常詳細的介紹了關于 Vue 的各個方面,圖文并茂、深入淺出的講解了關于 Vue 3 的概念和知識。總之 Vue 3 的文檔對于初學者來說非常友好。如果你對英文比較熟悉,推薦直接閱讀英文官方文檔,其中内容一般是最新的。
除開閱讀官方文檔以外,筆者還推薦閱讀優秀的 Vue 3 開源項目,例如 Element+、Ant Design Vue、Vue-Admin-Beautiful,Github 上有很多優秀的 Vue 3 項目,閱讀它們的源碼可以幫助你熟悉如何使用 Vue 3,以及建構大型項目的代碼組織方式。
當然,自己動手用 Vue 3 實踐一個前端項目能夠幫助你深入了解 Vue 3 的原理和開發方式,特别是将 Vue 3 的新特性用在工作項目中。筆者在了解了 Vue 3 的基礎文法和新特性之後,将所學知識運用在了自己的開源項目中,邊學邊做,就非常快速的掌握了 Vue 3 的核心知識。
總結
這篇文章主要介紹了 Vue 3 在大型前端項目中的優勢,尤其是新特性 TS 支援群組合式 API,能夠大幅增強代碼的可讀性和可維護性。這讓本身就上手容易的 Vue 架構變得如虎添翼,使其能夠勝任大型前端項目的設計和開發。對 TS 的原生支援,能夠讓 Vue 3 的項目代碼能夠具有良好的可預測性。而組合式 API,能夠将散亂的代碼邏輯變得更有秩序。這些都有助于增強 Vue 3 前端項目的健壯性,進而讓前端人員更容易編寫出穩定而可維護的代碼。另外,本文還通過筆者的一個開發中的前端項目(Crawlab Frontend),來示範如何利用 Vue 3 開發企業級前端項目,并展示了相關的項目結構、TS 類型聲明以及元件化,等等。
比較資深的前端工程師可能會對 Vue 3 的新特性不屑一顧,因為所謂的 TS 支援群組合式 API 都在其他知名架構以其他名字被率先引入,例如 React 的 React Hooks,Vue 3 似乎隻是借鑒了過去。但是,這種觀點非常不可取。在技術面前,任何方案都沒有高低貴賤,隻有合不合适。就像相親一樣,隻有合适的,才是最好的。尤雨溪也承認,AngularJS 和 React 都有很多優秀的技術,Vue 也借鑒了一部分。但你絕不能是以而宣判它是抄襲。就像 C# 跟 Java 文法和特性類似,但你肯定無法證明 C# 是抄襲的 Java(其實 C# 相較于 Java 有很多優秀特性,例如隐式類型推斷,這也是筆者比較喜歡 C# 的原因之一)。Vue 的成功,絕對不是偶然性的,它的易用性和相對豐富的文檔資源,讓初學者能夠快速上手,這對于前端開發者來說是福音。我們做技術的應該對新技術抱有包容心,能夠辯證而理性的看待問題,這樣才不緻于變得偏激進而走火入魔。
參考
- Vue 3 官方文檔: https://www.vue3js.cn/docs/zh/
- TypeScript 官方文檔: https://www.typescriptlang.org/docs
- Crawlab: https://github.com/crawlab-team/crawlab
- Crawlab Frontend: https://github.com/crawlab-team/crawlab-frontend
- 《為什麼說 TypeScript 是開發大型前端項目的必備語言》
本文分享自華為雲社群《TS 加持的 Vue 3,如何幫你輕松建構企業級前端應用》,原文作者:Marvin Zhang 。
點選關注,第一時間了解華為雲新鮮技術~