本文整理來自深入Vue3+TypeScript技術(shù)棧-coderwhy大神新課抬驴,只作為個人筆記記錄使用等舔,請大家多支持王紅元老師。
認識Vue
Vue (讀音 /vju?/狡忙,類似于 view) 是一套用于構(gòu)建用戶界面的漸進式框架洗做,全稱是Vue.js或者Vuejs弓叛。
什么是漸進式框架呢?
表示我們可以在項目中一點點來引入和使用Vue诚纸,而不一定需要全部使用Vue來開發(fā)整個項目撰筷。
目前Vue在前端處于什么地位?
目前前端最流行的是三大框架:Vue畦徘、React毕籽、Angular。
誰是最好的前端框架井辆?
我們從現(xiàn)實的角度关筒,分析一下,學習哪一門語言更容易找到工作杯缺?
- 找后端的工作:優(yōu)先推薦Java蒸播、其次推薦Go、再次推薦Node(JavaScript),可能不推薦PHP袍榆、C#
- 找前端的工作:優(yōu)先推薦JavaScript(TypeScript)胀屿、其次Flutter、再次Android(Java包雀、Kotlin)宿崭、iOS(OC、 Swift)
那么才写,就前端來說葡兑,學習了HTML、CSS琅摩、JavaScript铁孵,哪一個框架更容易找到工作?
- 如果去國外找工作房资,優(yōu)先推薦React蜕劝、其次是Vue和Angular,不推薦jQuery了
- 如果在國內(nèi)找工作轰异,優(yōu)先推薦岖沛、必須學習Vue,其次是React搭独,其次是Angular婴削,不推薦jQuery了
目前需要學習Vue3嗎?
在2020年的9月19日牙肝,萬眾期待的Vue3終于發(fā)布了正式版唉俗,命名為“One Piece”。
它也帶來了很多新的特性:更好的性能配椭、更小的包體積虫溜、更好的TypeScript集成、更優(yōu)秀的API設(shè)計股缸。
那么現(xiàn)在是否是學習vue3的時間呢衡楞?
答案是肯定的。
首先vue3在經(jīng)過一系列的更新和維護后敦姻,已經(jīng)是趨于穩(wěn)定瘾境,并且在之前尤雨溪也宣布在今年(2021年)第二季度會將vue3作為Vue CLI的默認版本了。
目前社區(qū)也經(jīng)過一定時間的沉淀镰惦,更加的完善了迷守,包括AntDesignVue、Element-Plus
都提供了對Vue3的支持陨献,所以很多公司目前新的項目都已經(jīng)在使用Vue3來進行開發(fā)了盒犹。
并且在面試的時候,幾乎都會問到各種各樣Vue3、Vite2工具相關(guān)的問題急膀。
Vue3帶來的變化
① 源碼
-
源碼通過monorepo的形式來管理源代碼
- Mono:單個沮协,Repo:repository倉庫,主要是將許多項目的代碼存儲在同一個repository中
- 這樣做的目的是多個包本身相互獨立卓嫂,可以有自己的功能邏輯慷暂、單元測試等,同時又在同一個倉庫下方便管理晨雳,而且模塊劃分的更加清晰行瑞,可維護性、可擴展性更強
-
源碼使用TypeScript來進行重寫
- 在Vue2.x的時候餐禁,Vue使用Flow來進行類型檢測
- 在Vue3.x的時候血久,Vue的源碼全部使用TypeScript來進行重構(gòu),并且Vue本身對TypeScript支持也更好了
② 性能
-
使用Proxy進行數(shù)據(jù)劫持
- 在Vue2.x的時候帮非,Vue2是使用Object.defineProperty來劫持數(shù)據(jù)的getter和setter方法的氧吐。這種方式一致存在一個缺陷就是當給對象添加或者刪除屬性時,是無法劫持和監(jiān)聽的末盔。所以在Vue2.x的時候筑舅,不得不提供一些特殊的API,比如$set或$delete陨舱,事實上都是一些hack方法翠拣,也增加了 開發(fā)者學習新的API的成本。
- 而在Vue3.x開始游盲,Vue使用Proxy來實現(xiàn)數(shù)據(jù)的劫持误墓,這個API的用法和相關(guān)的原理我也會在后續(xù)講到。
-
刪除了一些不必要的API
- 移除了實例上的$on, $off 和 $once益缎;
- 移除了一些特性:如filter优烧、內(nèi)聯(lián)模板等;
-
包括編譯方面的優(yōu)化
- 生成Block Tree链峭、Slot編譯優(yōu)化、diff算法優(yōu)化又沾;
③ 新的API
-
由Options API 到 Composition API
- 在Vue2.x的時候弊仪,我們會通過Options API來描述組件對象,Options API包括data杖刷、props励饵、methods、computed滑燃、生命周期等等這些選項役听。存在比較大的問題是多個邏輯可能是在不同的地方:比如created中會使用某一個method來修改data的數(shù)據(jù),代碼的內(nèi)聚性非常差。
- Composition API可以將相關(guān)聯(lián)的代碼放到同一處進行處理典予,而不需要在多個Options之間尋找甜滨。
-
Hooks函數(shù)增加代碼的復用性
- 在Vue2.x的時候,我們通常通過mixins在多個組件之間共享邏輯瘤袖,但是有一個很大的缺陷就是 mixins也是由一大堆的Options組成的衣摩,并且多個mixins會存在命名沖突的問題。
- 在Vue3.x中捂敌,我們可以通過Hook函數(shù)艾扮,來將一部分獨立的邏輯抽取出去,并且它們還可以做到是響應式的占婉。
- 具體的好處泡嘴,會在后續(xù)的課程中演練和講解(包括原理)。
系統(tǒng)學習Vue3+TypeScript
如何使用Vue呢逆济?
Vue的本質(zhì)酌予,就是一個JavaScript的庫。
剛開始我們不需要把它想象的非常復雜纹腌,我們就把它理解成一個已經(jīng)幫助我們封裝好的庫霎终,在項目中可以引入并且使用它即可。
那么安裝和使用Vue這個JavaScript庫有哪些方式呢升薯?
方式一:在頁面中通過CDN的方式來引入
方式二:下載Vue的JavaScript文件莱褒,并且自己手動引入
方式三:通過npm包管理工具安裝使用它(webpack再講)
方式四:直接通過Vue CLI創(chuàng)建項目,并且使用它
方式一:CDN引入
什么是CDN呢涎劈?CDN稱之為內(nèi)容分發(fā)網(wǎng)絡(luò)(Content Delivery Network或Content Distribution Network广凸,縮寫:CDN)。
它是指通過 相互連接的網(wǎng)絡(luò)系統(tǒng)蛛枚,利用最靠近每個用戶的服務(wù)器谅海,更快、更可靠地將音樂蹦浦、圖片扭吁、視頻、應用程序及其他文件發(fā)送給用戶盲镶,來提供高性能侥袜、可擴展性及低成本的網(wǎng)絡(luò)內(nèi)容傳遞給用戶。
常用的CDN服務(wù)器可以大致分為兩種:
- 自己的CDN服務(wù)器:需要購買自己的CDN服務(wù)器溉贿,目前阿里枫吧、 騰訊、亞馬遜宇色、Google等都可以購買CDN服務(wù)器九杂。
- 開源的CDN服務(wù)器:國際上使用比較多的是unpkg颁湖、 JSDelivr、cdnjs例隆。
Vue的CDN引入:
<script src="https://unpkg.com/vue@next"></script>
示例代碼如下:
<body>
<div id="app">
<h2>Hello World</h2>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const why = {
template: '<h2>Hello World</h2>'
}
const app = Vue.createApp(why);
app.mount("#app")
</script>
</body>
方式二:下載和引入
- 下載Vue的源碼
可以直接打開CDN的鏈接甥捺,復制其中所有的代碼,創(chuàng)建一個新的文件裳擎,比如vue.js涎永,將代碼復制到其中。 - 通過script標簽鹿响,引入剛才的文件:
<script src="../js/vue.js"></script>
示例代碼如下:
<body>
<div id="app"></div>
<script src="../js/vue.js"></script>
<script>
Vue.createApp({
template: `<h2>你好啊, 李銀河</h2>`
}).mount("#app");
</script>
</body>
計數(shù)器案例
通過計數(shù)器案例比較原生開發(fā)和Vue開發(fā)的區(qū)別羡微。
原生開發(fā):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h2 class="counter">0</h2>
<button class="increment">+1</button>
<button class="decrement">-1</button>
<script>
// 1.獲取所有的元素
const counterEl = document.querySelector(".counter");
const incrementEl = document.querySelector(".increment");
const decrementEl = document.querySelector(".decrement");
// 2.定義變量
let counter = 100;
counterEl.innerHTML = counter;
// 3.監(jiān)聽按鈕的點擊
incrementEl.addEventListener("click", () => {
counter += 1;
counterEl.innerHTML = counter;
});
decrementEl.addEventListener("click", () => {
counter -= 1;
counterEl.innerHTML = counter;
});
</script>
</body>
</html>
Vue開發(fā):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">哈哈哈哈啊</div>
<script src="../js/vue.js"></script>
<script>
Vue.createApp({
template: `
<div>
<h2>{{message}}</h2>
<h2>{{counter}}</h2>
<button @click='increment'>+1</button>
<button @click='decrement'>-1</button>
</div>
`,
data: function() {
return {
message: "Hello World",
counter: 100
}
},
// 定義各種各樣的方法
methods: {
increment() {
console.log("點擊了+1");
this.counter++;
},
decrement() {
console.log("點擊了-1");
this.counter--;
}
}
}).mount('#app');
</script>
</body>
</html>
可以發(fā)現(xiàn)Vue開發(fā)更簡潔。
聲明式和命令式
- 原生開發(fā)和Vue開發(fā)的模式和特點惶我。
我們會發(fā)現(xiàn)是完全不同的妈倔,這里其實涉及到兩種不同的編程范式:命令式編程和聲明式編程。
命令式編程關(guān)注的是 “how to do”绸贡,聲明式編程關(guān)注的是 “what to do”盯蝴,由框架(機器)完成 “how”的過程。 - 在原生的實現(xiàn)過程中听怕,我們是如何操作的呢捧挺?
我們每完成一個操作,都需要通過JavaScript編寫一條代碼尿瞭,來給瀏覽器一個指令闽烙;這樣的編寫代碼的過程,我們稱之為命令式編程声搁;在早期的原生JavaScript和jQuery開發(fā)的過程中黑竞,我們都是通過這種命令式的方式在編寫代碼的。 - 在Vue的實現(xiàn)過程中疏旨,我們是如何操作的呢很魂?
我們會在createApp傳入的對象中聲明需要的內(nèi)容,模板template檐涝、數(shù)據(jù)data遏匆、方法methods,這樣的編寫代碼的過程谁榜,我們稱之為是聲明式編程拉岁。目前Vue、React惰爬、Angular的編程模式,我們稱之為聲明式編程惫企,現(xiàn)在的SwiftUI也是聲明式編程撕瞧。
MVVM模型
MVC和MVVM都是一種軟件的體系結(jié)構(gòu)陵叽。
- MVC是Model – View –Controller的簡稱,是在前期被使用非炒园妫框架的架構(gòu)模式巩掺,比如iOS、前端
- MVVM是Model-View-ViewModel的簡稱页畦,是目前非常流行的架構(gòu)模式
通常情況下胖替,我們也經(jīng)常稱Vue是一個MVVM的框架。
Vue官方其實有說明豫缨,Vue雖然并沒有完全遵守MVVM的模型独令,但是整個設(shè)計是受到它的啟發(fā)的。
在上面使用createApp的時候好芭,我們傳入了一個對象燃箭,接下來我們詳細解析一下之前傳入的屬性分別代表什么含義。
template屬性
template屬性:表示的是Vue需要幫助我們渲染的模板信息舍败。
- 目前我們看到它里面有很多的HTML標簽招狸,這些標簽會替換掉我們掛載到的元素(比如id為app的div)的innerHTML
- 模板中有一些奇怪的語法,比如 {{}}邻薯,比如 @click裙戏,這些都是模板特有的語法,但是這個模板的寫法有點過于別扭了厕诡,并且IDE沒有任何提示累榜,阻礙我們編程的效率
Vue提供了兩種方式解決上面說的問題:
- 方式一:使用script標簽,并且標記它的類型為 x-template木人,設(shè)置id
- 方式二:使用任意標簽(通常使用template標簽信柿,因為不會被瀏覽器渲染),設(shè)置id
template元素是一種用于保存客戶端內(nèi)容的機制醒第,該內(nèi)容再加載頁面時不會被呈現(xiàn)渔嚷,但隨后可以在運行時使用JavaScript實例化。
template寫法
方式一:使用script標簽
<script type="x-template" id="why">
<div>
<h2>{{message}}</h2>
<h2>{{counter}}</h2>
<button @click='increment'>+1</button>
<button @click='decrement'>-1</button>
</div>
</script>
方式二:使用template(推薦)
<template id="why">
<div>
<h2>{{message}}</h2>
<h2>{{counter}}</h2>
<button @click='increment'>+1</button>
<button @click='decrement'>-1</button>
<button @click="btnClick">按鈕</button>
</div>
</template>
這個時候稠曼,在createApp的對象中形病,我們需要傳入的template以 # 開頭,如果字符串是以 # 開始霞幅,那么它將被用作 querySelector漠吻,并且使用匹配元素的 innerHTML 作為模板字符串。
data屬性
data屬性是傳入一個函數(shù)司恳,并且該函數(shù)需要返回一個對象途乃。
- 在Vue2.x的時候,也可以傳入一個對象(雖然官方推薦是一個函數(shù))
- 在Vue3.x的時候扔傅,必須傳入一個函數(shù)耍共,否則就會直接在瀏覽器中報錯
data中返回的對象會被Vue的響應式系統(tǒng)劫持烫饼,之后對該對象的修改或者訪問都會在劫持中被處理。
- 所以我們在template中通過 {{counter}} 訪問counter试读,可以從對象中獲取到數(shù)據(jù)
- 所以我們修改counter的值時杠纵,template中的 {{counter}}也會發(fā)生改變
- 具體這種響應式的原理,我們后面會有專門的篇幅來講解钩骇。
methods屬性
methods屬性是一個對象比藻,通常我們會在這個對象中定義很多的方法,這些方法可以被綁定到 template 模板中倘屹,在該方法中银亲,我們可以使用this關(guān)鍵字來直接訪問到data中返回的對象的屬性。
對于有經(jīng)驗的同學唐瀑,在這里我提一個問題群凶,官方文檔有這么一段描述:
問題一:為什么不能使用箭頭函數(shù)(官方文檔有給出解釋)?
問題二:不使用箭頭函數(shù)的情況下哄辣,this到底指向的是什么请梢?(可以作為一道面試題)
① 問題一:不能使用箭頭函數(shù)?
我們在methods中要使用data返回對象中的數(shù)據(jù)力穗,那么這個this是必須有值的毅弧,并且應該可以通過this獲取到data返回對象中的數(shù)據(jù)。
那么我們這個this能不能是window呢当窗?
不可以是window够坐,因為window中我們無法獲取到data返回對象中的數(shù)據(jù),但是如果我們使用箭頭函數(shù)崖面,那么這個this就會是window了元咙。
為什么是window呢?
這里涉及到箭頭函數(shù)使用this的查找規(guī)則巫员,它會在自己的上層作用于中來查找this庶香,最終剛好找到的是script作用于中的this,所以就是window简识。
this到底是如何查找和綁定的呢赶掖?
在coderwhy的公眾號有另外一篇文章,專門詳細的講解了this的綁定規(guī)則:https://mp.weixin.qq.com/s/hYm0JgBI25grNG_2sCRlTA七扰,認真學習之后你絕對對this的綁定一清二楚奢赂。
② 問題二:this到底指向什么?
事實上Vue的源碼當中就是對methods中的所有函數(shù)進行了遍歷颈走,并且通過bind綁定了this:
其他屬性
當然膳灶,這里還可以定義很多其他的屬性,我們會在后續(xù)進行講解立由,比如props轧钓、computed司致、watch、emits聋迎、setup等等。也包括很多的生命周期函數(shù)枣耀,不用著急霉晕,我們會一個個學習它們的。
Vue的源碼
如果想要學習Vue3的源碼捞奕,比如看createApp的實現(xiàn)過程牺堰,應該怎么辦呢?
- 在GitHub上搜索 vue-next(Vue3在github上叫vue-next)颅围,根據(jù)Tags下載非beta版本最新的源代碼伟葫,這里推薦通過 git clone 的方式下載。
- 安裝Vue源碼項目相關(guān)的依賴:
執(zhí)行 yarn install
- 對項目執(zhí)行打包操作:
執(zhí)行yarn dev(執(zhí)行前修改腳本)
- 通過
packages/vue/dist/vue.global.js
調(diào)試代碼
VSCode代碼片段
我們在前面練習Vue的過程中院促,有些代碼片段是需要經(jīng)常寫的筏养,我們在VSCode中我們可以生成一個代碼片段,方便我們快速生成常拓。VSCode中的代碼片段有固定的格式渐溶,所以我們一般會借助于一個在線工具來完成。
具體的步驟如下:
第一步弄抬,復制自己需要生成代碼片段的代碼茎辐;
第二步,https://snippet-generator.app/在該網(wǎng)站中生成代碼片段掂恕;
第三步拖陆,在VSCode中配置代碼片段;
代碼片段過程: