點擊上方“藍色字體”,選擇“設爲星標”
一、設計目標
不以解決實際業務痛點的更新都是耍流氓,下面我們來列舉一下Vue3
之前我們或許會面臨的問題
-
隨着功能的增長,複雜組件的代碼變得越來越難以維護
-
缺少一種比較「乾淨」的在多個組件之間提取和複用邏輯的機制
-
類型推斷不夠友好
-
bundle
的時間太久了
而 Vue3
經過長達兩三年時間的籌備,做了哪些事情?
我們從結果反推
-
更小 -
更快 -
TypeScript支持 -
API設計一致性 -
提高自身可維護性 -
開放更多底層功能
一句話概述,就是更小更快更友好了
更小
Vue3
移除一些不常用的 API
引入tree-shaking
,可以將無用模塊“剪輯”,僅打包需要的,使打包的整體體積變小了
更快
主要體現在編譯方面:
-
diff算法優化 -
靜態提升 -
事件監聽緩存 -
SSR優化
下篇文章我們會進一步介紹
更友好
vue3
在兼顧vue2
的options API
的同時還推出了composition API
,大大增加了代碼的邏輯組織和代碼複用能力
這裏代碼簡單演示下:
存在一個獲取鼠標位置的函數
import { toRefs, reactive } from 'vue';
function useMouse(){
const state = reactive({x:0,y:0});
const update = e=>{
state.x = e.pageX;
state.y = e.pageY;
}
onMounted(()=>{
window.addEventListener('mousemove',update);
})
onUnmounted(()=>{
window.removeEventListener('mousemove',update);
})
return toRefs(state);
}
我們只需要調用這個函數,即可獲取x
、y
的座標,完全不用關注實現過程
試想一下,如果很多類似的第三方庫,我們只需要調用即可,不必關注實現過程,開發效率大大提高
同時,VUE3
是基於typescipt
編寫的,可以享受到自動的類型定義提示
三、優化方案
vue3
從很多層面都做了優化,可以分成三個方面:
-
源碼 -
性能 -
語法 API
源碼
源碼可以從兩個層面展開:
-
源碼管理 -
TypeScript
源碼管理
vue3
整個源碼是通過 monorepo
的方式維護的,根據功能將不同的模塊拆分到packages
目錄下面不同的子目錄中
這樣使得模塊拆分更細化,職責劃分更明確,模塊之間的依賴關係也更加明確,開發人員也更容易閱讀、理解和更改所有模塊源碼,提高代碼的可維護性
另外一些 package
(比如 reactivity
響應式庫)是可以獨立於 Vue
使用的,這樣用戶如果只想使用 Vue3
的響應式能力,可以單獨依賴這個響應式庫而不用去依賴整個 Vue
TypeScript
Vue3
是基於typeScript
編寫的,提供了更好的類型檢查,能支持複雜的類型推導
性能
vue3
是從什麼哪些方面對性能進行進一步優化呢?
-
體積優化 -
編譯優化 -
數據劫持優化
這裏講述數據劫持:
在vue2
中,數據劫持是通過Object.defineProperty
,這個 API 有一些缺陷,並不能檢測對象屬性的添加和刪除
Object.defineProperty(data, 'a',{
get(){
// track
},
set(){
// trigger
}
})
儘管Vue
爲了解決這個問題提供了 set
和delete
實例方法,但是對於用戶來說,還是增加了一定的心智負擔
同時在面對嵌套層級比較深的情況下,就存在性能問題
default {
data: {
a: {
b: {
c: {
d: 1
}
}
}
}
}
相比之下,vue3
是通過proxy
監聽整個對象,那麼對於刪除還是監聽當然也能監聽到
同時Proxy
並不能監聽到內部深層次的對象變化,而 Vue3
的處理方式是在getter
中去遞歸響應式,這樣的好處是真正訪問到的內部對象纔會變成響應式,而不是無腦遞歸
語法 API
這裏當然說的就是composition API
,其兩大顯著的優化:
-
優化邏輯組織 -
優化邏輯複用
邏輯組織
一張圖,我們可以很直觀地感受到 Composition API
在邏輯組織方面的優勢
相同功能的代碼編寫在一塊,而不像options API
那樣,各個功能的代碼混成一塊
邏輯複用
在vue2
中,我們是通過mixin
實現功能混合,如果多個mixin
混合,會存在兩個非常明顯的問題:命名衝突和數據來源不清晰
而通過composition
這種形式,可以將一些複用的代碼抽離出來作爲一個函數,只要的使用的地方直接進行調用即可
同樣是上文的獲取鼠標位置的例子
import { toRefs, reactive, onUnmounted, onMounted } from 'vue';
function useMouse(){
const state = reactive({x:0,y:0});
const update = e=>{
state.x = e.pageX;
state.y = e.pageY;
}
onMounted(()=>{
window.addEventListener('mousemove',update);
})
onUnmounted(()=>{
window.removeEventListener('mousemove',update);
})
return toRefs(state);
}
組件使用
import useMousePosition from './mouse'
export default {
setup() {
const { x, y } = useMousePosition()
return { x, y }
}
}
可以看到,整個數據來源清晰了,即使去編寫更多的hook
函數,也不會出現命名衝突的問題
參考文獻
-
https://juejin.cn/post/6850418112878575629#heading-5 -
https://vue3js.cn/docs/zh
編後
由 笑妄²º²¹ 大佬主導,羣友共同貢獻整理
點擊關注下方卡片👇,在後臺回覆關鍵詞 5000
如果覺得這篇文章還不錯,來個【分享、點贊、在看】三連吧,讓更多的人也看到~
本文分享自微信公衆號 - 前端佈道師(honeyBadger8)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。