Skip to content

Commit fddbf06

Browse files
Boost performance
1 parent f1f12b1 commit fddbf06

File tree

5 files changed

+96
-57
lines changed

5 files changed

+96
-57
lines changed

src/lib/creator.js

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const checkDestroyed = (state) => {
2222
if (!state.$ctx) throw new Error('[EF] This component has been destroyed!')
2323
}
2424

25-
const bindTextNode = (ctx, {apply, node}) => {
25+
const bindTextNode = (ctx, node, apply) => {
2626
// Data binding text node
2727
const textNode = DOM.document.createTextNode('')
2828
const { dataNode, handlerNode, _key } = initBinding(ctx, {bind: node})
@@ -40,7 +40,7 @@ const bindTextNode = (ctx, {apply, node}) => {
4040
apply(textNode)
4141
}
4242

43-
const updateMountNode = ({ctx, key, value}) => {
43+
const updateMountNode = (ctx, key, value) => {
4444
const {children} = ctx
4545
const child = children[key]
4646
const {anchor, node} = child
@@ -56,27 +56,27 @@ const updateMountNode = ({ctx, key, value}) => {
5656
}
5757
// Update stored value
5858
child.node = value
59-
if (value) value.$mount({target: anchor, parent: ctx.state, option: mountOptions.BEFORE, key})
59+
if (value) value.$mount({target: anchor, parent: ctx.state, option: mountOptions.AFTER, key})
6060
exec()
6161
}
6262

63-
const updateMountList = ({ctx, key, value}) => {
63+
const updateMountList = (ctx, key, value) => {
6464
const {children} = ctx
6565
const {anchor, node} = children[key]
6666
if (ARR.equals(node, value)) return
6767
inform()
6868
if (node.length) node.clear()
6969
if (value) {
7070
value = ARR.copy(value)
71-
useFragment((fragment, putBack) => {
71+
useFragment((fragment, recycleFragment) => {
7272
// Update components
7373
for (let item of value) DOM.append(fragment, shared.toEFComponent(item).$mount({parent: ctx.state, key}))
7474
// Update stored value
7575
ARR.push(node, ...value)
7676
// Append to current component
7777
queueDom(() => {
7878
DOM.after(anchor, fragment)
79-
putBack()
79+
recycleFragment()
8080
})
8181
})
8282
}
@@ -89,6 +89,7 @@ const mountPointUpdaters = [
8989
]
9090

9191
const applyMountPoint = (type, key, tpl) => {
92+
const updater = mountPointUpdaters[type]
9293
Object.defineProperty(tpl.prototype, key, {
9394
get() {
9495
if (process.env.NODE_ENV !== 'production') checkDestroyed(this)
@@ -97,24 +98,26 @@ const applyMountPoint = (type, key, tpl) => {
9798
set(value) {
9899
if (process.env.NODE_ENV !== 'production') checkDestroyed(this)
99100
const ctx = this.$ctx
100-
mountPointUpdaters[type]({ctx, key, value})
101+
updater(ctx, key, value)
101102
},
102103
enumerable: true
103104
})
104105
}
105106

106-
const bindMountNode = ({ctx, key, anchor}) => {
107+
const bindMountNode = (ctx, key, anchor) => {
107108
const { children } = ctx
108109
const info = {anchor}
109110
children[key] = info
110111
anchor[EFMountPoint] = info
111112
}
112113

113-
const bindMountList = ({ctx, key, anchor}) => {
114+
// eslint-disable-next-line max-params
115+
const bindMountList = (ctx, key, anchor, aftAnchor) => {
114116
const { children } = ctx
115117
children[key] = {
116-
node: defineArr([], {ctx, key, anchor}),
117-
anchor
118+
node: defineArr([], {ctx, key, anchor, aftAnchor}),
119+
anchor,
120+
aftAnchor
118121
}
119122
anchor[EFMountPoint] = children[key]
120123
}
@@ -137,19 +140,23 @@ const resolveAST = (ctx, {apply, node, nodeType, namespace, create}) => {
137140
// Recursive call for child element
138141
if (typeOf(node[0]) === 'object') apply(create(ctx, {node, namespace}))
139142
// Dynamic text node
140-
else bindTextNode(ctx, {apply, node})
143+
else bindTextNode(ctx, node, apply)
141144
break
142145
}
143146
// Mount points
144147
case 'object': {
148+
if (process.env.NODE_ENV !== 'production') apply(DOM.document.createComment(`<MountPoint${node.t && ' type="list" ' || ' '}name="${node.n}">`))
145149
const anchor = DOM.document.createTextNode('')
146-
// Single node mount point
147-
if (node.t === 0) bindMountNode({ctx, key: node.n, anchor})
148-
// Multi node mount point
149-
else bindMountList({ctx, key: node.n, anchor})
150150
// Append anchor
151-
if (process.env.NODE_ENV !== 'production') apply(DOM.document.createComment(`<MountPoint${node.t && ' type="list" ' || ' '}name="${node.n}">`))
152151
apply(anchor)
152+
// Single node mount point
153+
if (node.t === 0) bindMountNode(ctx, node.n, anchor)
154+
else {
155+
// Multi node mount point
156+
const aftAnchor = DOM.document.createTextNode('')
157+
apply(aftAnchor)
158+
bindMountList(ctx, node.n, anchor, aftAnchor)
159+
}
153160
if (process.env.NODE_ENV !== 'production') apply(DOM.document.createComment('</MountPoint>'))
154161
break
155162
}
@@ -211,7 +218,7 @@ const create = (ctx, {node, namespace}) => {
211218
if (namespace === htmlNS) namespace = ''
212219

213220
// First create an element according to the description
214-
const [element, type] = createElement(ctx, {info, namespace, fragment, custom})
221+
const [element, type] = createElement(ctx, info, namespace, fragment, custom)
215222

216223
let apply = noop
217224

src/lib/element-creator.js

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import {hasColon, splitByColon} from './utils/string-ops.js'
1010

1111
const typeValid = obj => ['number', 'boolean', 'string'].indexOf(typeof obj) > -1
1212

13-
const createByTag = ({tagType, tagName, tagContent, attrs, namespace}) => {
13+
// eslint-disable-next-line max-params
14+
const createByTag = (tagType, tagName, tagContent, attrs, namespace) => {
1415
switch (tagType) {
1516
case 'string': {
1617
if (tagName === tagContent && attrs && attrs.is && typeof attrs.is === 'string') {
@@ -44,8 +45,9 @@ const createByTag = ({tagType, tagName, tagContent, attrs, namespace}) => {
4445
}
4546
}
4647

47-
const getElement = ({tagType, tagName, tagContent, attrs, ref, refs, namespace}) => {
48-
const element = createByTag({tagType, tagName, tagContent, attrs, namespace})
48+
// eslint-disable-next-line max-params
49+
const getElement = (tagType, tagName, tagContent, attrs, ref, refs, namespace) => {
50+
const element = createByTag(tagType, tagName, tagContent, attrs, namespace)
4951
if (ref) Object.defineProperty(refs, ref, {
5052
value: element,
5153
enumerable: true
@@ -59,7 +61,7 @@ const getVal = (dataNode, key) => {
5961
return data
6062
}
6163

62-
const regTmpl = (ctx, {val, handler}) => {
64+
const regTmpl = (ctx, val, handler) => {
6365
if (ARR.isArray(val)) {
6466
const [strs, ...exprs] = val
6567

@@ -99,7 +101,8 @@ const regTmpl = (ctx, {val, handler}) => {
99101
return () => val
100102
}
101103

102-
const applyEventListener = ({element, custom, handler, trigger: {l, s, i, p, h, a, c, t, u, e, o, k}}) => {
104+
// eslint-disable-next-line max-params
105+
const applyEventListener = (element, custom, handler, {l, s, i, p, h, a, c, t, u, e, o, k}) => {
103106

104107
/*
105108
* l: listener : string
@@ -189,7 +192,8 @@ const applyEventListener = ({element, custom, handler, trigger: {l, s, i, p, h,
189192
element[addListener](l, eventHandler, eventOptions)
190193
}
191194

192-
const addValListener = (ctx, {trigger, updateLock, element, lastNode, key, expr, custom}) => {
195+
// eslint-disable-next-line max-params
196+
const addValListener = (ctx, trigger, updateLock, element, lastNode, key, expr, custom) => {
193197
const addListener = custom && '$on' || 'addEventListener'
194198
const {parentNode, _key} = initBinding(ctx, {bind: expr})
195199

@@ -206,7 +210,7 @@ const addValListener = (ctx, {trigger, updateLock, element, lastNode, key, expr,
206210
}
207211

208212
if (trigger) {
209-
applyEventListener({element, custom, handler, trigger})
213+
applyEventListener(element, custom, handler, trigger)
210214
} else if (key === 'value') {
211215
// Listen to input, keyup and change events in order to work in most browsers.
212216
element[addListener]('input', handler, eventOptions)
@@ -268,7 +272,8 @@ const getAttrHandler = (ctx, {element, key, custom}) => {
268272
}
269273
}
270274

271-
const addAttr = (ctx, {element, attr, key, custom}) => {
275+
// eslint-disable-next-line max-params
276+
const addAttr = (ctx, element, attr, key, custom) => {
272277
if (typeValid(attr)) {
273278
if (custom) {
274279
if (attr === '') {
@@ -293,10 +298,11 @@ const addAttr = (ctx, {element, attr, key, custom}) => {
293298
}
294299

295300
const handler = getAttrHandler(ctx, {element, key, custom})
296-
regTmpl(ctx, {val: attr, handler})
301+
regTmpl(ctx, attr, handler)
297302
}
298303

299-
const addProp = (ctx, {element, propPath, value, trigger, updateOnly, custom}) => {
304+
// eslint-disable-next-line max-params
305+
const addProp = (ctx, element, value, propPath, trigger, updateOnly, custom) => {
300306
const keyPath = ARR.copy(propPath)
301307
const lastKey = keyPath.pop()
302308
if (custom) keyPath.unshift('$data')
@@ -319,27 +325,28 @@ const addProp = (ctx, {element, propPath, value, trigger, updateOnly, custom}) =
319325
}
320326
}
321327

322-
regTmpl(ctx, {val: value, handler})
328+
regTmpl(ctx, value, handler)
323329
if (
324330
trigger ||
325331
(propPath.length === 1 && (lastKey === 'value' || lastKey === 'checked')) &&
326332
!value[0]
327333
) {
328-
addValListener(ctx, {trigger, updateLock, element, lastNode, key: lastKey, expr: value[1], custom})
334+
addValListener(ctx, trigger, updateLock, element, lastNode, lastKey, value[1], custom)
329335
}
330336
}
331337
}
332338

333339
const rawHandler = val => val
334340

335-
const addEvent = (ctx, {element, trigger, custom}) => {
341+
// eslint-disable-next-line max-params
342+
const addEvent = (ctx, element, trigger, custom) => {
336343

337344
/*
338345
* m: method : string
339346
* v: value : string/array/undefined
340347
*/
341348
const {m, v} = trigger
342-
const _handler = regTmpl(ctx, {val: v, ctx, handler: rawHandler})
349+
const _handler = regTmpl(ctx, v, rawHandler)
343350

344351
const callEventHandler = (event) => {
345352
const value = _handler()
@@ -351,10 +358,11 @@ const addEvent = (ctx, {element, trigger, custom}) => {
351358
}
352359
}
353360

354-
applyEventListener({element, custom, handler: callEventHandler, trigger})
361+
applyEventListener(element, custom, callEventHandler, trigger)
355362
}
356363

357-
const createElement = (ctx, {info, namespace, fragment, custom}) => {
364+
// eslint-disable-next-line max-params
365+
const createElement = (ctx, info, namespace, fragment, custom) => {
358366
if (fragment) return [new EFFragment(), 'fragment']
359367

360368
/*
@@ -368,10 +376,10 @@ const createElement = (ctx, {info, namespace, fragment, custom}) => {
368376
const tagName = t
369377
const tagContent = ctx.scope[t] || t
370378
const tagType = typeof tagContent
371-
const element = getElement({tagType, tagName, tagContent, attrs: a, ref: r, refs: ctx.refs, namespace})
372-
if (a) for (let key in a) addAttr(ctx, {element, custom, attr: a[key], key})
373-
if (p) for (let [propPath, value, trigger, updateOnly] of p) addProp(ctx, {element, custom, value, propPath, trigger, updateOnly})
374-
if (e) for (let trigger of e) addEvent(ctx, {element, custom, trigger})
379+
const element = getElement(tagType, tagName, tagContent, a, r, ctx.refs, namespace)
380+
if (a) for (let key in a) addAttr(ctx, element, a[key], key, custom)
381+
if (p) for (let [propPath, value, trigger, updateOnly] of p) addProp(ctx, element, value, propPath, trigger, updateOnly, custom)
382+
if (e) for (let trigger of e) addEvent(ctx, element, trigger, custom)
375383

376384
return [element, tagType]
377385
}

src/lib/renderer.js

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,14 @@ const EFBaseComponent = class {
127127
}
128128

129129
const mount = () => {
130-
if (placeholder.parentNode) DOM.before(placeholder, element)
131-
else DOM.remove(element)
130+
const parentNode = placeholder.parentNode
131+
if (mount.remove || !parentNode) {
132+
DOM.remove(element)
133+
mount.remove = false
134+
} else if (parentNode) {
135+
DOM.before(placeholder, element)
136+
DOM.remove(placeholder)
137+
}
132138
}
133139

134140
const ctx = {
@@ -182,7 +188,15 @@ const EFBaseComponent = class {
182188

183189
element = create(ctx, {node: ast, namespace: ''})
184190

191+
let firstElement = element
192+
193+
while (!DOM.isNodeInstance(firstElement)) {
194+
if (isInstance(firstElement, EFFragment)) firstElement = firstElement.firstElement
195+
else firstElement = firstElement.$ctx.nodeInfo.element
196+
}
197+
185198
nodeInfo.element = element
199+
nodeInfo.firstElement = firstElement
186200

187201
for (let [path, handler] of watchers) {
188202
this.$subscribe(path, handler)
@@ -232,7 +246,6 @@ const EFBaseComponent = class {
232246
if (process.env.NODE_ENV !== 'production') checkDestroyed(this)
233247
const { nodeInfo, mount, beforeMount, afterMount } = this.$ctx
234248

235-
236249
let ret = null
237250

238251
if (typeof target === 'string') {
@@ -252,32 +265,35 @@ const EFBaseComponent = class {
252265
if (!key) key = '__DIRECTMOUNT__'
253266
nodeInfo.parent = parent
254267
nodeInfo.key = key
268+
mount.remove = false
255269
queueDom(mount)
256270

271+
const placeholder = nodeInfo.placeholder
272+
257273
if (target) {
258274
switch (option) {
259275
case mountOptions.BEFORE: {
260-
DOM.before(target, nodeInfo.placeholder)
276+
DOM.before(target, placeholder)
261277
break
262278
}
263279
case mountOptions.AFTER: {
264-
DOM.after(target, nodeInfo.placeholder)
280+
DOM.after(target, placeholder)
265281
break
266282
}
267283
case mountOptions.REPLACE: {
268-
DOM.before(target, nodeInfo.placeholder)
284+
DOM.before(target, placeholder)
269285
DOM.remove(target)
270286
break
271287
}
272288
case mountOptions.APPEND:
273289
default: {
274-
DOM.append(target, nodeInfo.placeholder)
290+
DOM.append(target, placeholder)
275291
}
276292
}
277293
ret = exec()
278294
} else {
279295
exec()
280-
ret = nodeInfo.placeholder
296+
ret = placeholder
281297
}
282298

283299
if (afterMount) afterMount()
@@ -310,7 +326,7 @@ const EFBaseComponent = class {
310326
} else if (isInstance(parent, EFFragment)) parent.$ctx.nodeInfo.element.removeChild(nodeInfo.element)
311327
}
312328

313-
DOM.remove(nodeInfo.placeholder)
329+
mount.remove = true
314330
queueDom(mount)
315331

316332
const ret = exec()

0 commit comments

Comments
 (0)