ranuts 0.1.0-alpha.1 → 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/package.json +1 -1
  2. package/dist/src/file/fileInfo.d.ts +0 -7
  3. package/dist/src/file/fs.d.ts +0 -2
  4. package/dist/src/file/readDir.d.ts +0 -6
  5. package/dist/src/file/readFile.d.ts +0 -8
  6. package/dist/src/file/watchFile.d.ts +0 -8
  7. package/dist/src/file/writeFile.d.ts +0 -8
  8. package/dist/src/mode/subscribe.d.ts +0 -16
  9. package/dist/src/ranlog/behavior.d.ts +0 -1
  10. package/dist/src/ranlog/env.d.ts +0 -5
  11. package/dist/src/ranlog/error.d.ts +0 -2
  12. package/dist/src/ranlog/index.d.ts +0 -26
  13. package/dist/src/ranlog/performance.d.ts +0 -21
  14. package/dist/src/ranlog/report.d.ts +0 -7
  15. package/dist/src/ranlog/request.d.ts +0 -18
  16. package/dist/src/ranlog/utils.d.ts +0 -19
  17. package/dist/src/utils/filterObj.d.ts +0 -8
  18. package/dist/src/utils/str2Xml.d.ts +0 -8
  19. package/dist/src/vnode/h.d.ts +0 -6
  20. package/dist/src/vnode/hooks.d.ts +0 -23
  21. package/dist/src/vnode/htmlDomApi.d.ts +0 -33
  22. package/dist/src/vnode/init.d.ts +0 -2
  23. package/dist/src/vnode/is.d.ts +0 -5
  24. package/dist/src/vnode/modules/attributes.d.ts +0 -8
  25. package/dist/src/vnode/modules/class.d.ts +0 -8
  26. package/dist/src/vnode/modules/index.d.ts +0 -7
  27. package/dist/src/vnode/modules/listeners.d.ts +0 -14
  28. package/dist/src/vnode/modules/props.d.ts +0 -8
  29. package/dist/src/vnode/modules/style.d.ts +0 -14
  30. package/dist/src/vnode/vnode.d.ts +0 -31
  31. package/src/astParser/Parser.ts +0 -654
  32. package/src/astParser/Tokenizer.ts +0 -447
  33. package/src/astParser/nodeTypes.ts +0 -194
  34. package/src/astParser/utils.ts +0 -27
  35. package/src/babel/parser.ts +0 -10
  36. package/src/colors/fmt.ts +0 -29
  37. package/src/colors/isColorSupported.ts +0 -13
  38. package/src/file/appendFile.ts +0 -29
  39. package/src/file/fileInfo.ts +0 -22
  40. package/src/file/fs.ts +0 -9
  41. package/src/file/readDir.ts +0 -18
  42. package/src/file/readFile.ts +0 -26
  43. package/src/file/watchFile.ts +0 -31
  44. package/src/file/writeFile.ts +0 -38
  45. package/src/mode/subscribe.ts +0 -89
  46. package/src/ran/commit.ts +0 -0
  47. package/src/ran/dom.ts +0 -0
  48. package/src/ran/hooks.ts +0 -0
  49. package/src/ran/reconcile.ts +0 -0
  50. package/src/ran/schedule.ts +0 -0
  51. package/src/ranlog/behavior.ts +0 -5
  52. package/src/ranlog/console.ts +0 -16
  53. package/src/ranlog/env.ts +0 -29
  54. package/src/ranlog/error.ts +0 -11
  55. package/src/ranlog/performance.ts +0 -65
  56. package/src/ranlog/report.ts +0 -33
  57. package/src/ranlog/request.ts +0 -60
  58. package/src/ranlog/utils.ts +0 -92
  59. package/src/ranpack/ast/Declaration.ts +0 -120
  60. package/src/ranpack/ast/Node.ts +0 -7
  61. package/src/ranpack/ast/Reference.ts +0 -32
  62. package/src/ranpack/ast/Scope.ts +0 -80
  63. package/src/ranpack/bundle.ts +0 -50
  64. package/src/ranpack/graph.ts +0 -143
  65. package/src/ranpack/module.ts +0 -431
  66. package/src/ranpack/moduleLoader.ts +0 -73
  67. package/src/ranpack/plugins.ts +0 -70
  68. package/src/ranpack/statement.ts +0 -66
  69. package/src/ranpack/utils/buildScope.ts +0 -77
  70. package/src/ranpack/utils/findReference.ts +0 -36
  71. package/src/ranpack/utils/isFunctionDeclaration.ts +0 -41
  72. package/src/ranpack/utils/makeLegalIdentifier.ts +0 -18
  73. package/src/ranpack/utils/object.ts +0 -8
  74. package/src/ranpack/utils/resolve.ts +0 -32
  75. package/src/ranpack/utils/walk.ts +0 -66
  76. package/src/ranpack/ws.ts +0 -269
  77. package/src/server/connectType.ts +0 -9
  78. package/src/server/encodeUrl.ts +0 -46
  79. package/src/server/escapeHtml.ts +0 -46
  80. package/src/server/get.ts +0 -36
  81. package/src/server/jitter.ts +0 -77
  82. package/src/server/mimeType.ts +0 -858
  83. package/src/server/paresUrl.ts +0 -40
  84. package/src/server/send.ts +0 -89
  85. package/src/server/server.ts +0 -67
  86. package/src/server/status.ts +0 -191
  87. package/src/server/traverse.ts +0 -54
  88. package/src/server/websocket.ts +0 -200
  89. package/src/sort/bubble.ts +0 -21
  90. package/src/sort/bucket.ts +0 -11
  91. package/src/sort/count.ts +0 -10
  92. package/src/sort/heap.ts +0 -10
  93. package/src/sort/insert.ts +0 -20
  94. package/src/sort/merge.ts +0 -35
  95. package/src/sort/quick.ts +0 -50
  96. package/src/sort/radix.ts +0 -11
  97. package/src/sort/randomArray.ts +0 -21
  98. package/src/sort/select.ts +0 -23
  99. package/src/sort/shell.ts +0 -22
  100. package/src/utils/compose.ts +0 -37
  101. package/src/utils/filterObj.ts +0 -21
  102. package/src/utils/mergeObj.ts +0 -12
  103. package/src/utils/startTask.ts +0 -15
  104. package/src/utils/str2Xml.ts +0 -26
  105. package/src/utils/taskEnd.ts +0 -14
  106. package/src/vnode/h.ts +0 -108
  107. package/src/vnode/hooks.ts +0 -25
  108. package/src/vnode/htmlDomApi.ts +0 -199
  109. package/src/vnode/init.ts +0 -429
  110. package/src/vnode/is.ts +0 -17
  111. package/src/vnode/modules/attributes.ts +0 -70
  112. package/src/vnode/modules/class.ts +0 -46
  113. package/src/vnode/modules/listeners.ts +0 -123
  114. package/src/vnode/modules/props.ts +0 -41
  115. package/src/vnode/modules/style.ts +0 -118
  116. package/src/vnode/vnode.ts +0 -65
package/src/vnode/init.ts DELETED
@@ -1,429 +0,0 @@
1
- // 虚拟dom
2
- import type { VNode } from './vnode'
3
- import { vnode } from './vnode'
4
- // 引入操作的dom api的相关方法
5
- import type { DOMAPI } from './htmlDomApi'
6
- import { htmlDomApi } from './htmlDomApi'
7
- // 类型判断
8
- import * as is from './is'
9
- // 导入模块
10
- import type { ModuleHook } from './modules';
11
- import { modules } from './modules'
12
-
13
- type NonUndefined<T> = T extends undefined ? never : T
14
-
15
- type KeyToIndexMap = { [key: string]: number }
16
-
17
- interface Cbs {
18
- [key: string]: ModuleHook[]
19
- create: Array<ModuleHook>
20
- update: Array<ModuleHook>
21
- destroy: Array<(oldVnode: VNode, vnode?: VNode) => void>
22
- }
23
-
24
- // 如果2个VNode节点的key和sel属性都相同,我们就认为它们是相同的VNode节点
25
- function sameVnode(vnode1: VNode, vnode2: VNode): boolean {
26
- return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel
27
- }
28
-
29
- // 判断是否为Vnode
30
- function isVnode(vnode: any): vnode is VNode {
31
- return vnode.sel !== undefined
32
- }
33
-
34
- // 根据children item的key属性,创建Key Map
35
- function createKeyToOldIdx(
36
- children: VNode[],
37
- beginIdx: number,
38
- endIdx: number,
39
- ): KeyToIndexMap {
40
- const map: KeyToIndexMap = {}
41
- for (let i = beginIdx; i <= endIdx; ++i) {
42
- const key = children[i]?.key
43
- if (key !== undefined) {
44
- map[key] = i
45
- }
46
- }
47
- return map
48
- }
49
-
50
- // 创建一个空白VNode,用于createElm中触发create钩子函数时调用
51
- const emptyNode = vnode('', {}, [], undefined, undefined)
52
-
53
- export function init(): (oldVnode: VNode | Element, vnode: VNode) => VNode {
54
- // 获取操作html dom的api
55
- const api: DOMAPI = htmlDomApi
56
-
57
- // 用于缓存各个模块的钩子函数
58
- const cbs: Cbs = {
59
- create: [],
60
- update: [],
61
- destroy: [],
62
- }
63
- // 遍历cbs
64
- for (const key of Object.keys(cbs)) {
65
- // 初始化为数组
66
- cbs[key] = []
67
- // 遍历modules
68
- for (const module of Object.keys(modules)) {
69
- // 获取模块中对应的生命周期
70
- const hook = modules[module][key]
71
- // 如果生命周期有值
72
- if (hook !== undefined) {
73
- // 将其加入cbs对应的属性中
74
- cbs[key].push(hook)
75
- }
76
- }
77
- }
78
-
79
- // 创建一个只有标签名和选择器的空白VNode
80
- function emptyNodeAt(elm: Element) {
81
- const id = elm.id ? '#' + elm.id : ''
82
- const c = elm.className ? '.' + elm.className.split(' ').join('.') : ''
83
- return vnode(
84
- api.tagName(elm).toLowerCase() + id + c,
85
- {},
86
- [],
87
- undefined,
88
- elm,
89
- )
90
- }
91
-
92
- // 判断是否为undefined
93
- function isUndef(s: unknown): boolean {
94
- return s === undefined
95
- }
96
-
97
- // 判断是否为defined
98
- function isDef<A>(s: A): s is NonUndefined<A> {
99
- return s !== undefined
100
- }
101
-
102
- // 根据VNode创建dom
103
- function createElm(vnode: VNode): Node {
104
- // 缓存循环children中的index
105
- let i: number
106
- // 缓存VNode的children
107
- const children = vnode.children
108
- // 缓存VNode的选择器
109
- const sel = vnode.sel
110
- // 把 vnode 转化成真实DOM对象(没有渲染到页面)
111
- if (sel === '!') {
112
- // 如果选择器是!,创建注释节点
113
- if (isUndef(vnode.text)) {
114
- vnode.text = ''
115
- }
116
- vnode.elm = api.createComment(`${vnode.text!}`)
117
- } else if (sel !== undefined) {
118
- // 如果选择器不为空,解析选择器
119
- // 缓存id
120
- const hashIdx = sel.indexOf('#')
121
- // 缓存class
122
- const dotIdx = sel.indexOf('.', hashIdx)
123
- // 缓存 # 的位置
124
- const hash = hashIdx > 0 ? hashIdx : sel.length
125
- // 缓存 . 的位置
126
- const dot = dotIdx > 0 ? dotIdx : sel.length
127
- // 缓存标签
128
- const tag =
129
- hashIdx !== -1 || dotIdx !== -1
130
- ? sel.slice(0, Math.min(hash, dot))
131
- : sel
132
- // 创建dom
133
- const elm = (vnode.elm = api.createElement(tag))
134
- // dom设置id
135
- if (hash < dot) elm.setAttribute('id', sel.slice(hash + 1, dot))
136
- // dom设置class
137
- if (dotIdx > 0)
138
- elm.setAttribute('class', sel.slice(dot + 1).replace(/\./g, ' '))
139
- // 触发各个模块的create钩子函数
140
- for (i = 0; i < cbs.create.length; ++i) {
141
- cbs.create[i](emptyNode, vnode)
142
- }
143
- // 如果vnode中有子节点,创建子vnode对应的DOM元素并追加到DOM树上
144
- if (is.array(children)) {
145
- for (i = 0; i < children.length; ++i) {
146
- const ch = children[i]
147
- if (ch != null) {
148
- api.appendChild(elm, createElm(ch as VNode))
149
- }
150
- }
151
- } else if (is.primitive(vnode.text)) {
152
- // 如果有子文本节点,也创建并追加到DOM树上
153
- api.appendChild(elm, api.createTextNode(`${vnode.text!}`))
154
- }
155
- } else {
156
- // 如果选择器为空,创建文本节点
157
- vnode.elm = api.createTextNode(`${vnode.text!}`)
158
- }
159
- // 返回新创建的DOM
160
- return vnode.elm
161
- }
162
-
163
- // 根据VNode新增dom
164
- function addVnodes(
165
- parentElm: Node,
166
- before: Node | null,
167
- vnodes: VNode[],
168
- startIdx: number,
169
- endIdx: number,
170
- ) {
171
- // 遍历传入的VNode数组,创建对应的dom,再将dom插入到指定的dom元素之前
172
- for (; startIdx <= endIdx; ++startIdx) {
173
- const ch = vnodes[startIdx]
174
- if (ch != null) {
175
- api.insertBefore(parentElm, createElm(ch), before)
176
- }
177
- }
178
- }
179
-
180
- // 触发destroy钩子函数
181
- function invokeDestroyHook(vnode: VNode) {
182
- // 获取VNode的data属性
183
- const data = vnode.data
184
- // 当data不为空时
185
- if (data !== undefined) {
186
- // 触发各个模块的destroy钩子函数
187
- for (let i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode)
188
- // 当VNode有子节点,且子节点不为字符串或数字,触发子节点VNode的destroy钩子函数
189
- if (vnode.children !== undefined) {
190
- for (let j = 0; j < vnode.children.length; ++j) {
191
- const child = vnode.children[j]
192
- if (
193
- child != null &&
194
- typeof child !== 'string' &&
195
- typeof child !== 'number'
196
- ) {
197
- invokeDestroyHook(child)
198
- }
199
- }
200
- }
201
- }
202
- }
203
-
204
- // 创建删除子节点dom的方法
205
- function createRmCb(childElm: Node) {
206
- return function rmCb() {
207
- // 这里是一个闭包将需要删除的dom节点缓存起来,方便之后调用rmCb方法删除
208
- const parent = api.parentNode(childElm) as Node
209
- api.removeChild(parent, childElm)
210
- }
211
- }
212
-
213
- // 删除VNode对应dom
214
- function removeVnodes(
215
- parentElm: Node,
216
- vnodes: VNode[],
217
- startIdx: number,
218
- endIdx: number,
219
- ): void {
220
- for (; startIdx <= endIdx; ++startIdx) {
221
- // 用于缓存删除dom的方法
222
- let rm: () => void
223
- // 获取当前要删除节点
224
- const ch = vnodes[startIdx]
225
- if (ch != null) {
226
- if (isDef(ch.sel)) {
227
- // 触发destroy钩子函数
228
- invokeDestroyHook(ch)
229
- /*
230
- * 在dom中这里需要判断remove钩子函数是否全部调用,而我们dom没有remove钩子函数,所以
231
- * 不需要判断
232
- */
233
- rm = createRmCb(ch.elm!)
234
- // 删除子节点
235
- rm()
236
- } else {
237
- // 删除文本节点
238
- api.removeChild(parentElm, ch.elm!)
239
- }
240
- }
241
- }
242
- }
243
-
244
- // 更新children
245
- function updateChildren(parentElm: Node, oldCh: VNode[], newCh: VNode[]) {
246
- // 旧VNode的children头索引
247
- let oldStartIdx = 0
248
- // 新VNode的children头索引
249
- let newStartIdx = 0
250
- // 旧VNode的children尾索引
251
- let oldEndIdx = oldCh.length - 1
252
- // 新VNode的children尾索引
253
- let newEndIdx = newCh.length - 1
254
- // 旧VNode的children的头VNode
255
- let oldStartVnode = oldCh[0]
256
- // 旧VNode的children的尾VNode
257
- let oldEndVnode = oldCh[oldEndIdx]
258
- // 新VNode的children的头VNode
259
- let newStartVnode = newCh[0]
260
- // 新VNode的children的尾VNode
261
- let newEndVnode = newCh[newEndIdx]
262
- // 旧VNode的children的Key Map
263
- let oldKeyToIdx: KeyToIndexMap | undefined
264
- // 用于缓存key相同的新旧VNode
265
- let idxInOld: number
266
- // 用于缓存将要移动的旧VNode
267
- let elmToMove: VNode
268
- // 用于缓存将要插入新增VNode的位置之前的VNode
269
- let before: any
270
-
271
- // 遍历新旧children数组,直到其中之一遍历完
272
- while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
273
- // 我们之后可能会对oldStartVnode、oldEndVnode、newStartVnode、newEndVnode重新赋值,可能会出现等于null的情况
274
- if (oldStartVnode == null) {
275
- oldStartVnode = oldCh[++oldStartIdx]
276
- } else if (oldEndVnode == null) {
277
- oldEndVnode = oldCh[--oldEndIdx]
278
- } else if (newStartVnode == null) {
279
- newStartVnode = newCh[++newStartIdx]
280
- } else if (newEndVnode == null) {
281
- newEndVnode = newCh[--newEndIdx]
282
- // key 和 sel 相同,则就是相同节点
283
- } else if (sameVnode(oldStartVnode, newStartVnode)) {
284
- // 当旧头VNode和新头VNode是相同VNode时,将新头VNode差异更新到旧头VNode上,同时将新旧头索引后移
285
- // 对比两个节点,如果newVnode有vnodeData,
286
- // 执行update钩子,更新oldNode上的模块的内容
287
- // 更新加载过的模块里的内容
288
- // 判断节点的类型,文本节点直接替换,如果不是文本节点
289
- // 判断是否有子元素,更新子元素
290
- patchVnode(oldStartVnode, newStartVnode)
291
- oldStartVnode = oldCh[++oldStartIdx]
292
- newStartVnode = newCh[++newStartIdx]
293
- } else if (sameVnode(oldEndVnode, newEndVnode)) {
294
- // 当旧尾VNode和新尾VNode是相同VNode时,将新尾VNode差异更新到旧尾VNode上,同时将新旧尾索引前移
295
- patchVnode(oldEndVnode, newEndVnode)
296
- oldEndVnode = oldCh[--oldEndIdx]
297
- newEndVnode = newCh[--newEndIdx]
298
- } else if (sameVnode(oldStartVnode, newEndVnode)) {
299
- /**
300
- * 当旧头VNode和新尾VNode是相同节点时,将新尾VNode差异更新到旧头VNode上,然后将旧头VNode插入到旧尾VNode后
301
- * 最后将旧头索引后移,新尾索引前移
302
- */
303
- patchVnode(oldStartVnode, newEndVnode)
304
- api.insertBefore(parentElm,oldStartVnode.elm!,api.nextSibling(oldEndVnode.elm!))
305
- oldStartVnode = oldCh[++oldStartIdx]
306
- newEndVnode = newCh[--newEndIdx]
307
- } else if (sameVnode(oldEndVnode, newStartVnode)) {
308
- /**
309
- * 当旧尾VNode和新头VNode是相同节点时,将新头VNode差异更新到旧尾VNode上,然后将旧尾VNode插入到旧头VNode前
310
- * 最后将旧尾索引前移,新头索引后移
311
- */
312
- patchVnode(oldEndVnode, newStartVnode)
313
- api.insertBefore(parentElm, oldEndVnode.elm!, oldStartVnode.elm!)
314
- oldEndVnode = oldCh[--oldEndIdx]
315
- newStartVnode = newCh[++newStartIdx]
316
- } else {
317
- // 如果没有Key Map则创建Key Map,用于根据key来更新VNode
318
- if (oldKeyToIdx === undefined) {
319
- oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
320
- }
321
- // 根据Key Map获取当前新头VNode的对应的旧VNode的index
322
- idxInOld = oldKeyToIdx[newStartVnode.key as string]
323
-
324
- if (isUndef(idxInOld)) {
325
- // 如果没有设置key属性,直接根据新头VNode创建dom元素,插入到旧头VNode对应dom之前
326
- api.insertBefore(
327
- parentElm,
328
- createElm(newStartVnode),
329
- oldStartVnode.elm!,
330
- )
331
- } else {
332
- // 如果设置key属性,获取到key对应的旧VNode
333
- elmToMove = oldCh[idxInOld]
334
- if (elmToMove.sel !== newStartVnode.sel) {
335
- // 如果旧VNode和新VNode的sel属性不同,则直接创建新VNode对应的dom,插入到旧头VNode对应dom之前
336
- api.insertBefore(
337
- parentElm,
338
- createElm(newStartVnode),
339
- oldStartVnode.elm!,
340
- )
341
- } else {
342
- // 如果sel属性相同,则将新VNode数据更新到旧VNode上
343
- patchVnode(elmToMove, newStartVnode)
344
- // 删除旧children对应的VNode,代表已经更新过
345
- oldCh[idxInOld] = undefined as any
346
- // 创建VNode对应的dom,插入到旧头VNode对应dom之前
347
- api.insertBefore(parentElm, elmToMove.elm!, oldStartVnode.elm!)
348
- }
349
- }
350
- // 将新头VNode设置为新children数组中新头索引后一位
351
- newStartVnode = newCh[++newStartIdx]
352
- }
353
- }
354
- // 循环完成后,当旧头索引小于等于旧尾索引,或新头索引大于等于新尾索引时,说明新旧children其中之一已经遍历完成
355
- if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) {
356
- // 如果存在旧头索引大于旧尾索引情况,说明新children中新增了VNode
357
- if (oldStartIdx > oldEndIdx) {
358
- // 获取新增VNode后一位的VNode对应的dom
359
- before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm
360
- // 将新增VNode对应dom插入对应dom树位置
361
- addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx)
362
- } else {
363
- // 删除多余dom节点
364
- removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)
365
- }
366
- }
367
- }
368
-
369
- // 对比新旧vnode差异,将差异更新到旧VNode上。
370
- function patchVnode(oldVnode: VNode, vnode: VNode) {
371
- // 当VNode的data属性存在时,触发update钩子函数
372
- if (vnode.data !== undefined) {
373
- for (let i = 0; i < cbs.update.length; ++i) {
374
- cbs.update[i](oldVnode, vnode)
375
- }
376
- }
377
-
378
- // 由于是相同的VNode节点,使用新旧VNode的真实dom元素相同
379
- const elm = (vnode.elm = oldVnode.elm!)
380
- // 获取旧VNode的children
381
- const oldCh = oldVnode.children as VNode[]
382
- // 获取新VNode的children
383
- const ch = vnode.children as VNode[]
384
-
385
- // 如果新旧节点完全相同,直接返回
386
- if (oldVnode === vnode) return
387
- // 判断VNode是否为文本节点
388
- if (isUndef(vnode.text)) {
389
- // 如果不是文本节点,判断新旧VNode是否同时有children
390
- if (isDef(oldCh) && isDef(ch)) {
391
- // 如果同时有children属性,且children属性不相同就更新children
392
- if (oldCh !== ch) {
393
- updateChildren(elm, oldCh, ch)
394
- }
395
- }
396
- }
397
- }
398
-
399
- return function patch(oldVnode: VNode | Element, vnode: VNode): VNode {
400
- // 缓存dom节点和父dom节点
401
- let elm: Node, parent: Node
402
-
403
- // 当oldVnode不是VNode时,说明是初次加载,创建一个空白VNode
404
- if (!isVnode(oldVnode)) {
405
- oldVnode = emptyNodeAt(oldVnode)
406
- }
407
-
408
- // 判断是否为相同VNode节点
409
- if (sameVnode(oldVnode, vnode)) {
410
- // 更新VNode节点差异
411
- patchVnode(oldVnode, vnode)
412
- } else {
413
- // 获取旧VNode的dom
414
- elm = oldVnode.elm!
415
- // 获取父节点dom
416
- parent = api.parentNode(elm) as Node
417
- // 创建dom元素
418
- createElm(vnode)
419
- // 当父节点不为空时
420
- if (parent != null) {
421
- // 将新创建的dom插入dom树
422
- api.insertBefore(parent, vnode.elm!, api.nextSibling(elm))
423
- // 删除旧VNode节点
424
- removeVnodes(parent, [oldVnode], 0, 0)
425
- }
426
- }
427
- return vnode
428
- }
429
- }
package/src/vnode/is.ts DELETED
@@ -1,17 +0,0 @@
1
- import type { VNode } from './vnode'
2
-
3
- // 判断是否为数组
4
- export const array = Array.isArray
5
-
6
- export const isStr = (str: unknown): str is string => {
7
- return typeof str === 'string'
8
- }
9
- // 判断是否为字符串或数字
10
- export function primitive(s: unknown): s is string | number {
11
- return typeof s === 'string' || typeof s === 'number'
12
- }
13
- // 判断是否为vnode
14
- export function isVnode(s: any): s is VNode {
15
- return !!s?.sel
16
- }
17
-
@@ -1,70 +0,0 @@
1
- import type { VNode, VNodeData } from '../vnode'
2
-
3
- export type Attrs = Record<string, string | number | boolean>
4
-
5
- const xlinkNS = 'http://www.w3.org/1999/xlink'
6
- const xmlNS = 'http://www.w3.org/XML/1998/namespace'
7
- const colonChar = 58
8
- const xChar = 120
9
-
10
- function updateAttrs(oldVnode: VNode, vnode: VNode): void {
11
- // 用于缓存attrs的name
12
- let key: string
13
- // 用于缓存Vnode的dom
14
- const elm: Element = vnode.elm as Element
15
- // 用于缓存旧VNode的attrs
16
- let oldAttrs = oldVnode.data && oldVnode.data.attrs
17
- // 用于缓存新VNode的attrs
18
- let attrs = vnode.data && vnode.data.attrs
19
-
20
- // 如果新旧VNode都没有attrs属性,直接返回
21
- if (!oldAttrs && !attrs) return
22
- // 如果新旧VNode的attrs属性相同,直接返回
23
- if (oldAttrs === attrs) return
24
- // 如果旧VNode没有attrs,将其设置为空对象
25
- oldAttrs = oldAttrs || {}
26
- // 如果新VNode没有attrs,将其设置为空对象
27
- attrs = attrs || {}
28
-
29
- // 遍历新VNode的attrs
30
- for (key in attrs) {
31
- // 获取当前attrs的值
32
- const cur = attrs[key]
33
- // 获取旧VNode对应的attrs的值
34
- const old = oldAttrs[key]
35
- // 如果新旧VNode的attrs值不相同
36
- if (old !== cur) {
37
- // 如果新VNode的attrs值为true
38
- if (cur === true) {
39
- // 通过setAttribute设置为空字符串
40
- elm.setAttribute(key, '')
41
- } else if (cur === false) {
42
- // 如果新VNode的attrs值为false,则删除key
43
- elm.removeAttribute(key)
44
- } else {
45
- // 设置svg的属性
46
- if (key.charCodeAt(0) !== xChar) {
47
- elm.setAttribute(key, cur as any)
48
- } else if (key.charCodeAt(3) === colonChar) {
49
- // Assume xml namespace
50
- elm.setAttributeNS(xmlNS, key, cur as any)
51
- } else if (key.charCodeAt(5) === colonChar) {
52
- // Assume xlink namespace
53
- elm.setAttributeNS(xlinkNS, key, cur as any)
54
- } else {
55
- // 通过setAttribute设置值
56
- elm.setAttribute(key, `${cur}`)
57
- }
58
- }
59
- }
60
- }
61
- // 遍历旧VNode的attrs
62
- for (key in oldAttrs) {
63
- // 如果新VNode的attrs中没有相同的key,则直接删除该attrs属性
64
- if (!(key in attrs)) {
65
- elm.removeAttribute(key)
66
- }
67
- }
68
- }
69
-
70
- export const attributesModule = { create: updateAttrs, update: updateAttrs }
@@ -1,46 +0,0 @@
1
- import type { VNode, VNodeData } from '../vnode'
2
-
3
- export type Classes = Record<string, boolean>
4
-
5
- function updateClass(oldVnode: VNode, vnode: VNode): void {
6
- // 用于缓存遍历中当前class属性的值
7
- let cur: any
8
- // 用于缓存遍历中当前class的name
9
- let name: string
10
- // 获取新VNode的dom元素
11
- const elm: Element = vnode.elm as Element
12
- // 获取旧VNode的class数据
13
- let oldClass = oldVnode.data && oldVnode.data.class
14
- // 获取新VNode的class数据
15
- let className = vnode.data && vnode.data.class
16
-
17
- // 如果新旧VNode都没有class,直接返回
18
- if (!oldClass && !className) return
19
- // 如果新旧VNode完全相同,直接返回
20
- if (oldClass === className) return
21
- // 如果旧VNode没有class,将其设置为空对象
22
- oldClass = oldClass || {}
23
- // 如果新VNode没有class,将其设置为空对象
24
- className = className || {}
25
-
26
- // 遍历旧VNode的class
27
- for (name in oldClass) {
28
- // 如果当前class旧VNode上有但新VNode没有,则删除该VNode
29
- if (
30
- oldClass[name] &&
31
- !Object.prototype.hasOwnProperty.call(className, name)
32
- ) {
33
- elm.classList.remove(name)
34
- }
35
- }
36
- // 遍历新Vnodde的class
37
- for (name in className) {
38
- // 如果新旧VNode的class值不同,则根据新VNode的class值是true or false来判断是新增还是删除class
39
- cur = className[name]
40
- if (cur !== oldClass[name]) {
41
- (elm.classList as any)[cur ? 'add' : 'remove'](name)
42
- }
43
- }
44
- }
45
-
46
- export const classModule = { create: updateClass, update: updateClass }
@@ -1,123 +0,0 @@
1
- import type { VNode, VNodeData } from '../vnode'
2
-
3
- const isFunction = (handler: unknown): handler is Function => {
4
- return typeof handler === 'function'
5
- }
6
-
7
- type Listener<T> = (this: VNode, ev: T, vnode: VNode) => void
8
-
9
- export type On = {
10
- [N in keyof HTMLElementEventMap]?:
11
- | Listener<HTMLElementEventMap[N]>
12
- | Array<Listener<HTMLElementEventMap[N]>>
13
- } & {
14
- [event: string]: Listener<any> | Array<Listener<any>>
15
- }
16
-
17
- type SomeListener<N extends keyof HTMLElementEventMap> =
18
- | Listener<HTMLElementEventMap[N]>
19
- | Listener<any>
20
-
21
- function invokeHandler<N extends keyof HTMLElementEventMap>(
22
- handler: SomeListener<N> | Array<SomeListener<N>>,
23
- vnode: VNode,
24
- event?: Event,
25
- ): void {
26
- if (isFunction(handler)) {
27
- // 如果类型是function,说明只有一个事件监听,将this指向vnode调用
28
- (handler as Function).call(vnode, event, vnode)
29
- } else if (typeof handler === 'object') {
30
- // 如果类型是对象,说明有多个事件监听,遍历依次调用
31
- for (let i = 0; i < handler.length; i++) {
32
- invokeHandler(handler[i], vnode, event)
33
- }
34
- }
35
- }
36
-
37
- function handleEvent(event: Event, vnode: VNode) {
38
- const name = event.type
39
- const on = vnode.data && vnode.data.on
40
-
41
- // 如果on中存在事件监听,则进行运行
42
- if (on && on[name]) {
43
- invokeHandler(on[name], vnode, event)
44
- }
45
- }
46
-
47
- // 创建一个事件监听的闭包,这样可以确保每次创建的都是一个独立的事件监听
48
- function createListener() {
49
- return function handler(event: Event) {
50
- handleEvent(event, (handler as any).vnode)
51
- }
52
- }
53
-
54
- function updateEventListeners(oldVnode: VNode, vnode?: VNode): void {
55
- // 获取旧VNode中监听的事件
56
- const oldOn = oldVnode?.data?.on
57
- // 获取旧VNode中已经创建的监听事件
58
- const oldListener = oldVnode?.listener
59
- // 获取旧VNode的dom
60
- const oldElm: Element = oldVnode.elm as Element
61
- // 获取新VNode中监听的事件
62
- const on = vnode?.data?.on
63
- // 获取新VNode中已经创建的监听事件
64
- const elm: Element = (vnode && vnode.elm) as Element
65
- // 缓存遍历中当前事件的名称
66
- let name: string
67
-
68
- // 如果新旧VNode监听事件完全一样,直接返回
69
- if (oldOn === on) {
70
- return
71
- }
72
-
73
- // 如果旧VNode中有已经创建的事件监听
74
- if (oldOn && oldListener) {
75
- // 如果新VNode中没有事件监听
76
- if (!on) {
77
- for (name in oldOn) {
78
- // 删除旧VNode中的事件监听
79
- oldElm.removeEventListener(name, oldListener, false)
80
- }
81
- } else {
82
- // 如果新VNode中有事件监听,则遍历旧VNode
83
- for (name in oldOn) {
84
- // 如果新VNode中没有当前的事件监听,则删除该事件监听
85
- if (!on[name]) {
86
- oldElm.removeEventListener(name, oldListener, false)
87
- }
88
- }
89
- }
90
- }
91
-
92
- // 如果新VNode有事件监听
93
- if (on) {
94
- // 如果新VNode上已经存在事件监听,则直接继承,如果没有则创建一个新事件监听
95
- const listener = vnode.listener = oldVnode.listener || createListener()
96
- // 更新listener上的vnode
97
- // listener.vnode = vnode
98
-
99
- // 如果旧VNode没有事件监听
100
- if (!oldOn) {
101
- // 遍历新VNode上的事件监听
102
- for (name in on) {
103
- // 将其添加到dom上
104
- elm.addEventListener(name, listener, false)
105
- }
106
- } else {
107
- // 如果旧VNode有事件监听
108
- // 遍历新VNode上的事件监听
109
- for (name in on) {
110
- // 将旧VNode上没有的事件监听添加到dom上
111
- if (!oldOn[name]) {
112
- elm.addEventListener(name, listener, false)
113
- }
114
- }
115
- }
116
- }
117
- }
118
-
119
- export const eventListenersModule = {
120
- create: updateEventListeners,
121
- update: updateEventListeners,
122
- destroy: updateEventListeners,
123
- }