休息一下

恭喜你完成 Minimum Example 部分!現在你已經親手體驗了 Vue.js 的核心組成部分。
最小範例部分結束了!
在開始時,我提到這本書分為幾個部分,第一部分「最小範例部分」現在已經完成。做得好!
如果你對虛擬 DOM 或補丁渲染感興趣,你可以繼續到基礎虛擬 DOM 部分。
如果你想進一步擴充元件,有基礎元件部分。如果你對模板中更豐富的運算式(如指令)感興趣,你可以探索基礎模板編譯器部分。
如果你對 script setup 或編譯器巨集感興趣,你可以繼續到基礎 SFC 編譯器部分。(當然,如果你願意,你可以全部做!!)
最重要的是,「最小範例部分」也是一個值得尊敬的部分,所以如果你覺得,「我不需要了解得太深入,但我想得到一個大致的想法」,那麼你到這裡就足夠了。
到目前為止我們取得了什麼成就?
最後,讓我們反思一下我們在最小範例部分做了什麼以及取得了什麼成就。
我們現在知道我們在看什麼以及它屬於哪裡
首先,透過名為 createApp 的初始開發者介面,我們了解了(web 應用)開發者和 Vue 世界是如何連接的。
具體來說,從我們在開始時進行的重構開始,你現在應該了解 Vue 目錄結構的基礎,它的相依性以及開發者正在工作的地方。
讓我們比較目前目錄和 vuejs/core 的目錄。
chibivue 
*原始程式碼太大,無法在截圖中顯示,所以省略了。
儘管它很小,你現在應該能夠在某種程度上閱讀和理解每個檔案的角色和內容。
我希望你也會挑戰自己閱讀我們這次沒有涵蓋的部分的原始碼。(你應該能夠一點一點地閱讀它!)
我們現在知道宣告式 UI 是如何實作的
透過 h 函式的實作,我們了解了宣告式 UI 是如何實作的。
// 在內部,它產生一個像 {tag, props, children} 這樣的物件,並基於它執行 DOM 操作
h('div', { id: 'my-app' }, [
h('p', {}, ['Hello!']),
h(
'button',
{
onClick: () => {
alert('hello')
},
},
['Click me!'],
),
])這是虛擬 DOM 之類的東西首次出現的地方。
我們現在知道響應式系統是什麼以及如何動態更新螢幕
我們了解了 Vue 獨特功能響應式系統的實作,它是如何工作的以及它實際上是什麼。
const targetMap = new WeakMap<any, KeyToDepMap>()
function reactive<T extends object>(target: T): T {
const proxy = new Proxy(target, {
get(target: object, key: string | symbol, receiver: object) {
track(target, key)
return Reflect.get(target, key, receiver)
},
set(
target: object,
key: string | symbol,
value: unknown,
receiver: object,
) {
Reflect.set(target, key, value, receiver)
trigger(target, key)
return true
},
})
}const component = {
setup() {
const state = reactive({ count: 0 }) // 建立代理
const increment = () => {
state.count++ // 觸發
}
;() => {
return h('p', {}, `${state.count}`) // 追蹤
}
},
}我們現在知道虛擬 DOM 是什麼,為什麼它有益,以及如何實作它
作為使用 h 函式渲染的改進,我們透過比較了解了使用虛擬 DOM 的高效渲染方法。
// 虛擬 DOM 的介面
export interface VNode<HostNode = any> {
type: string | typeof Text | object
props: VNodeProps | null
children: VNodeNormalizedChildren
el: HostNode | undefined
}
// 首先,呼叫渲染函式
const render: RootRenderFunction = (rootComponent, container) => {
const vnode = createVNode(rootComponent, {}, [])
// 第一次,n1 是 null。在這種情況下,每個過程執行 mount
patch(null, vnode, container)
}
const patch = (n1: VNode | null, n2: VNode, container: RendererElement) => {
const { type } = n2
if (type === Text) {
processText(n1, n2, container)
} else if (typeof type === 'string') {
processElement(n1, n2, container)
} else if (typeof type === 'object') {
processComponent(n1, n2, container)
} else {
// do nothing
}
}
// 從第二次開始,將前一個 VNode 和目前 VNode 傳遞給 patch 函式以更新差異
const nextVNode = component.render()
patch(prevVNode, nextVNode)我了解了元件的結構以及元件之間的交互是如何實作的。
export interface ComponentInternalInstance {
type: Component
vnode: VNode
subTree: VNode
next: VNode | null
effect: ReactiveEffect
render: InternalRenderFunction
update: () => void
propsOptions: Props
props: Data
emit: (event: string, ...args: any[]) => void
isMounted: boolean
}const MyComponent = {
props: { someMessage: { type: String } },
setup(props: any, { emit }: any) {
return () =>
h('div', {}, [
h('p', {}, [`someMessage: ${props.someMessage}`]),
h('button', { onClick: () => emit('click:change-message') }, [
'change message',
]),
])
},
}
const app = createApp({
setup() {
const state = reactive({ message: 'hello' })
const changeMessage = () => {
state.message += '!'
}
return () =>
h('div', { id: 'my-app' }, [
h(
MyComponent,
{
'some-message': state.message,
'onClick:change-message': changeMessage,
},
[],
),
])
},
})我了解了編譯器是什麼以及模板功能是如何實作的。
透過了解編譯器是什麼並實作模板編譯器,我獲得了如何實作更原始的類似 HTML 的實作以及如何實作 Vue 特定功能(如 Mustache 語法)的理解。
const app = createApp({
setup() {
const state = reactive({ message: 'Hello, chibivue!', input: '' })
const changeMessage = () => {
state.message += '!'
}
const handleInput = (e: InputEvent) => {
state.input = (e.target as HTMLInputElement)?.value ?? ''
}
return { state, changeMessage, handleInput }
},
template: `
<div class="container" style="text-align: center">
<h2>{{ state.message }}</h2>
<img
width="150px"
src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/1200px-Vue.js_Logo_2.svg.png"
alt="Vue.js Logo"
/>
<p><b>chibivue</b> is the minimal Vue.js</p>
<button @click="changeMessage"> click me! </button>
<br />
<label>
Input Data
<input @input="handleInput" />
</label>
<p>input value: {{ state.input }}</p>
<style>
.container {
height: 100vh;
padding: 16px;
background-color: #becdbe;
color: #2c3e50;
}
</style>
</div>
`,
})我了解了如何透過 Vite 外掛程式實作 SFC 編譯器。
透過實作模板編譯器並透過 Vite 外掛程式利用它,我獲得了如何實作將腳本,模板和樣式組合到一個檔案中的原始檔案格式的理解。
我還了解了 Vite 外掛程式可以做什麼,以及 transform 和虛擬模組。
<script>
import { reactive } from 'chibivue'
export default {
setup() {
const state = reactive({ message: 'Hello, chibivue!', input: '' })
const changeMessage = () => {
state.message += '!'
}
const handleInput = e => {
state.input = e.target?.value ?? ''
}
return { state, changeMessage, handleInput }
},
}
</script>
<template>
<div class="container" style="text-align: center">
<h2>{{ state.message }}</h2>
<img
width="150px"
src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/1200px-Vue.js_Logo_2.svg.png"
alt="Vue.js Logo"
/>
<p><b>chibivue</b> is the minimal Vue.js</p>
<button @click="changeMessage">click me!</button>
<br />
<label>
Input Data
<input @input="handleInput" />
</label>
<p>input value: {{ state.input }}</p>
</div>
</template>
<style>
.container {
height: 100vh;
padding: 16px;
background-color: #becdbe;
color: #2c3e50;
}
</style>關於未來
從現在開始,為了使其更實用,我們將在每個部分中更詳細地介紹。
我將稍微解釋一下每個部分要做什麼以及如何進行(政策)。
要做什麼
從這裡開始,它將分為 5 個部分 + 1 個附錄。
- 基礎虛擬 DOM 部分
- 排程器的實作
- 不支援的補丁的實作(主要與屬性相關)
- Fragment 的支援
- 基礎響應式系統部分
- ref API
- computed API
- watch API
- 基礎元件系統部分
- provide/inject
- 生命週期鉤子
- 基礎模板編譯器部分
- v-on
- v-bind
- v-for
- v-model
- 基礎 SFC 編譯器部分
- SFC 的基礎
- script setup
- 編譯器巨集
- Web 應用程式要點部分(附錄)
這部分是附錄。
在這部分中,我們將實作在 web 開發中經常與 Vue 一起使用的函式庫。
- store
- route
我們將涵蓋上述兩個,但請隨意實作其他想到的東西!
政策
在最小範例部分,我們相當詳細地解釋了實作步驟。
到現在,如果你已經實作了它,你應該能夠閱讀原始 Vue 的原始碼。
因此,從現在開始,解釋將保持粗略的政策,你將在閱讀原始程式碼或自己思考的同時實作實際程式碼。
(不-不,這不是我變得懶惰而不願意詳細寫作或類似的事情!)
嗯,按照書中所說的實作是有趣的,但一旦它開始成形,自己做更有趣,並且會導致更深的理解。
從這裡開始,請將這本書視為一種指導方針,主要內容在原始 Vue 原始碼中!

憑藉目前掌握的知識,你已經能夠閱讀 Vue.js 原始碼了。可以前往自己感興趣的章節,也可以直接深入原始程式碼,請依自己的方式享受探索過程!
