Vue3.0設計目標
- 更小
- 更快(*)
- 加強TypeScript支持(*)
- 加強API設計一致性
- 提高自身可維護性
- 開放更多底層功能
更快
- Object.defineProperty -> Proxy (顆粒度更大)
- Virtual Dom 重構
- 更多編譯優化:slot默認編譯為函數(不存在父子組件強耦合),Momomorphic vnode factory,Compiler-generated flags for vnode/children types
Virtual Dom 重構
傳統Virtual DOM的性能瓶頸
顆粒度是組件。
![Vue3.0簡單認識](http://p2.ttnews.xyz/loading.gif)
雖然Vue能夠保證觸發更新的組件最小化,但是單個組件內部依然需要遍歷該組件的整個Virtual DOM樹。
![Vue3.0簡單認識](http://p2.ttnews.xyz/loading.gif)
傳統Virtual DOM的性能跟模板大小正相關,跟動態節點的數量無關。在一些組件整個模板內只有少量動態節點的情況下,這些遍歷都是性能的浪費。
Vue3.0 Virtual DOM
動靜結合
- 節點結構完全不會改變
- 只有一個動態節點
節點結構變化 v-if
- v-if 外部:只有v-if是動態節點
- v-if 內部:只有 {{ message }} 是動態節點
節點結構變化 v-for
- v-for 外部:只有v-for是動態節點 (fragment)
- 每個v-for循環內部:只有 {{ item.message }} 是動態節點
區塊樹Block tree
- 將模板基於動態節點指令切割為嵌套的區塊
- 每個區塊內部的節點結構是固定的
- 每個區塊只需要以一個Array追蹤自身包含的動態節點
升級
新策略將Virtual DOM更新性能能由與模板整體大小相關提升為與動態內容的數量相關
TypeScript(略)
API設計
Fuction-based API
const App = {
setup() {
// data
const count = value(0)
// computed
const plusOne = computed(() => count.value + 1)
// method
const increment = () => { count.value++ }
// watch
watch(() => count.value * 2, v => console.log(v))
// lifecycle
onMounted(() => console.log('mounted!'))
// 暴露給模板或渲染函數
return { count }
}
}
複製代碼
優點
- 沒有命名空間衝突
- 數據來源清晰
- 沒有額外的組件性能消耗
對比Class API
- 更好的TypeScript類型推導支持
- 更靈活的邏輯複用能力
- Tree-shaking友好
- 代碼更容易被壓縮
更靈活的邏輯複用能力
鼠標位置偵聽:
定義
function useMousePosition() {
const x = value(0)
const y = value(0)
const update = e => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
複製代碼
使用
new Vue({
template: `
\t\t
\t\t\tMouse position: x {{ x }} / y {{ y }}
\t\t
\t`,
setup() {
const { x, y } = useMousePosition()
return { x, y }
}
})
複製代碼
對比React Hooks
- 同樣的邏輯組合、複用能力
- Vue只調用一次,符合js直覺,沒有閉包變量問題,沒有內存/GC壓力,不存在內聯回調導致子組件永遠更新的問題
閱讀更多 小可樂程序員 的文章