-
-
Notifications
You must be signed in to change notification settings - Fork 350
/
dom.ts
56 lines (52 loc) · 1.7 KB
/
dom.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import { Attributes, DOM, IFiber } from './type'
import { isStr, TAG } from './reconcile'
const defaultObj = {} as const
const jointIter = <P extends Attributes>(
aProps: P,
bProps: P,
callback: (name: string, a: any, b: any) => void
) => {
aProps = aProps || defaultObj as P
bProps = bProps || defaultObj as P
Object.keys(aProps).forEach(k => callback(k, aProps[k], bProps[k]))
Object.keys(bProps).forEach(k => !aProps.hasOwnProperty(k) && callback(k,undefined, bProps[k]))
}
export const updateElement = <P extends Attributes>(
dom: DOM,
aProps: P,
bProps: P
) => {
jointIter(aProps, bProps, (name, a, b) => {
if (a === b || name === 'children') {
} else if (name === 'style' && !isStr(b)) {
jointIter(a, b, (styleKey, aStyle, bStyle) => {
if (aStyle !== bStyle) {
;(dom as any)[name][styleKey] = bStyle || ''
}
})
} else if (name[0] === 'o' && name[1] === 'n') {
name = name.slice(2).toLowerCase() as Extract<keyof P, string>
if (a) dom.removeEventListener(name, a)
dom.addEventListener(name, b)
} else if (name in dom && !(dom instanceof SVGElement)) {
;(dom as any)[name] = b || ''
} else if (b == null || b === false) {
dom.removeAttribute(name)
} else {
dom.setAttribute(name, b)
}
})
}
export const createElement = <P = Attributes>(fiber: IFiber) => {
const dom =
fiber.type === '#text'
? document.createTextNode('')
: fiber.lane & TAG.SVG
? document.createElementNS(
'http://www.w3.org/2000/svg',
fiber.type as string
)
: document.createElement(fiber.type as string)
updateElement(dom as DOM, {} as P, fiber.props as P)
return dom
}