@@ -22,188 +22,4 @@ console.log(`MyComponent:${MyComponent}`)
22
22
```
23
23
<a href =" /run/defineComponent " target =" _blank " >亲自试一试</a >
24
24
25
- 那么 ` createApp ` 里面都干了什么呢?我们接着往下看
26
-
27
- ``` js
28
- export const createApp = ((... args ) => {
29
- const app = ensureRenderer ().createApp (... args)
30
-
31
- if (__DEV__ ) {
32
- injectNativeTagCheck (app)
33
- }
34
-
35
- const { mount } = app
36
- app .mount = (containerOrSelector: Element | string): any => {
37
- const container = normalizeContainer (containerOrSelector)
38
- if (! container) return
39
- const component = app ._component
40
- if (! isFunction (component) && ! component .render && ! component .template ) {
41
- component .template = container .innerHTML
42
- }
43
- // clear content before mounting
44
- container .innerHTML = ' '
45
- const proxy = mount (container)
46
- container .removeAttribute (' v-cloak' )
47
- return proxy
48
- }
49
-
50
- return app
51
- }) as CreateAppFunction< Element >
52
- ```
53
-
54
- 我们可以看到重点在于 ` ensureRenderer ` ,
55
-
56
- ``` js
57
- const rendererOptions = {
58
- patchProp, // 处理 props 属性
59
- ... nodeOps // 处理 DOM 节点操作
60
- }
61
-
62
- // lazy create the renderer - this makes core renderer logic tree-shakable
63
- // in case the user only imports reactivity utilities from Vue.
64
- let renderer: Renderer | HydrationRenderer
65
-
66
- let enabledHydration = false
67
-
68
- function ensureRenderer () {
69
- return renderer || (renderer = createRenderer (rendererOptions))
70
- }
71
- ```
72
- 调用 ` createRenderer `
73
-
74
- ``` js
75
- export function createRenderer<
76
- HostNode = RendererNode,
77
- HostElement = RendererElement
78
- >(options : RendererOptions < HostNode , HostElement > ) {
79
- return baseCreateRenderer< HostNode, HostElement> (options)
80
- }
81
- ```
82
- 调用 ` baseCreateRenderer ` , ` baseCreateRenderer ` 这个函数简直可以用庞大来形容,` vnode ` ` diff ` ` patch ` 均在这个方法中实现,回头我们再来细看实现,现在我们只需要关心他最后返回的什么
83
-
84
- ``` js
85
- function baseCreateRenderer (
86
- options : RendererOptions ,
87
- createHydrationFns ?: typeof createHydrationFunctions
88
- ): any {
89
- const {
90
- insert: hostInsert ,
91
- remove: hostRemove ,
92
- patchProp: hostPatchProp ,
93
- createElement: hostCreateElement ,
94
- createText: hostCreateText ,
95
- createComment: hostCreateComment ,
96
- setText: hostSetText ,
97
- setElementText: hostSetElementText ,
98
- parentNode: hostParentNode ,
99
- nextSibling: hostNextSibling ,
100
- setScopeId: hostSetScopeId = NOOP ,
101
- cloneNode: hostCloneNode,
102
- insertStaticContent: hostInsertStaticContent
103
- } = options
104
-
105
- // ....此处省略两千行,我们先不管
106
-
107
- return {
108
- render,
109
- hydrate,
110
- createApp: createAppAPI (render, hydrate)
111
- }
112
- }
113
-
114
- ```
115
-
116
- 从源码中我们看到 ` baseCreateRenderer ` 最终返回 ` render ` ` hydrate ` ` createApp ` 3个函数, 但在 ` createApp ` 这个函数中我们本质上只需要返回 ` createApp ` 这个函数就好,这里返回了3个,说明其它两个会在别处用到,具体哪里能用到,后面我们再回头看
117
-
118
- 接着将生成的 ` render ` 传给 ` createAppAPI ` 这个真正的 ` createApp ` 方法,` hydrate ` 为可选参数,` ssr ` 的场景下会用到,这边我们也先跳过
119
-
120
- 看了 ` baseCreateRenderer ` 这个函数,再看 ` createAppAPI ` 就会觉得太轻松了。。。毕竟不是一个量级的
121
-
122
- ` createAppAPI ` 首先判断
123
-
124
- ``` js
125
- export function createAppAPI<HostElement>(
126
- render : RootRenderFunction ,
127
- hydrate ?: RootHydrateFunction
128
- ): CreateAppFunction<HostElement> {
129
- return function createApp (rootComponent , rootProps = null ) {
130
- if (rootProps != null && ! isObject (rootProps)) {
131
- __DEV__ && warn (` root props passed to app.mount() must be an object.` )
132
- rootProps = null
133
- }
134
-
135
- // 创建默认APP配置
136
- const context = createAppContext ()
137
- const installedPlugins = new Set ()
138
-
139
- let isMounted = false
140
-
141
- const app: App = {
142
- _component: rootComponent as Component,
143
- _props: rootProps,
144
- _container: null ,
145
- _context: context,
146
-
147
- get config () {
148
- return context .config
149
- },
150
-
151
- set config (v ) {
152
- if (__DEV__ ) {
153
- warn (
154
- ` app.config cannot be replaced. Modify individual options instead.`
155
- )
156
- }
157
- },
158
-
159
- // 都是一些眼熟的方法
160
- use () {},
161
- mixin () {},
162
- component () {},
163
- directive () {},
164
-
165
- // mount 我们拎出来讲
166
- mount () {},
167
- unmount () {},
168
- // ...
169
- }
170
-
171
- return app
172
- }
173
- }
174
- ```
175
-
176
- ` createAppContext ` 实现
177
-
178
- ``` js
179
- export function createAppContext (): AppContext {
180
- return {
181
- config: {
182
- isNativeTag: NO ,
183
- devtools: true ,
184
- performance : false ,
185
- globalProperties: {},
186
- optionMergeStrategies: {},
187
- isCustomElement: NO ,
188
- errorHandler: undefined ,
189
- warnHandler: undefined
190
- },
191
- mixins: [],
192
- components: {},
193
- directives: {},
194
- provides: Object .create (null )
195
- }
196
- }
197
- ```
198
-
199
- 到这里,整个` createApp ` 流程就结束了,在整个环节中,我们故意忽略了很多细节,不过不重要 ,这个篇幅我们只需要` createApp ` 在主流程做了什么了就好
200
-
201
- 你可能会有很多疑问,怎么就没了,
202
-
203
- 模板是怎么编绎的?
204
- 生命周期是怎么挂载的?
205
- 组件是怎么注册的?
206
- 响应式怎么做到的?
207
-
208
- 等等,我们先记着,后面有篇幅单独拎出来
209
25
0 commit comments