Skip to content

Commit a16967a

Browse files
committed
Subtle semantics changes
1 parent c9d3709 commit a16967a

File tree

4 files changed

+95
-38
lines changed

4 files changed

+95
-38
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "js-element",
3-
"version": "0.0.224",
3+
"version": "0.0.225",
44
"description": "",
55
"license": "LGPL-3.0",
66
"main": "./index.js",

src/main/js-element-hooks.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,59 @@ export const useBeforeUnmount = hook(
370370
}
371371
)
372372

373+
// === useAfterInit =====================================================
374+
375+
export const useOnInit = hook('useOnInit', function (action: () => void) {
376+
const c = currentCtrl!
377+
const done = false
378+
379+
c.beforeMount(() => {
380+
if (done) {
381+
return
382+
}
383+
384+
action()
385+
})
386+
})
387+
388+
// === usePreEffect =====================================================
389+
390+
export const usePreEffect = hook(
391+
'usePreEffect',
392+
function (
393+
action: () => void | undefined | null | (() => void),
394+
getDeps?: () => any[]
395+
): void {
396+
let oldDeps: any[] | null = null
397+
let cleanup: Task | null | undefined | void
398+
const c = currentCtrl!
399+
400+
const callback = () => {
401+
let needsAction = getDeps === undefined
402+
403+
if (!needsAction) {
404+
const newDeps = getDeps!()
405+
406+
needsAction =
407+
oldDeps === null ||
408+
newDeps === null ||
409+
!isEqualArray(oldDeps, newDeps)
410+
411+
oldDeps = newDeps
412+
}
413+
414+
if (needsAction) {
415+
cleanup && cleanup()
416+
cleanup = action()
417+
}
418+
}
419+
420+
c.beforeMount(callback)
421+
c.beforeUpdate(callback)
422+
c.beforeUnmount(() => cleanup && cleanup())
423+
}
424+
)
425+
373426
// === useEffect =====================================================
374427

375428
export const useEffect = hook(

src/main/js-element.ts

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ type PropConfig =
5151
type Ctrl = {
5252
getName(): string
5353
getHost(): HTMLElement
54-
isInitialized(): boolean
54+
hasRendered(): boolean
5555
isMounted(): boolean
5656
hasUpdated(): boolean
5757
refresh(): void
58+
onceBeforeMount(task: () => void): void
5859
beforeMount(taks: () => void): void
5960
afterMount(task: () => void): void
6061
onceBeforeUpdate(task: () => void): void
@@ -194,11 +195,11 @@ function intercept(point: 'init' | 'render', fn: InterceptFn) {
194195

195196
class BaseElement extends HTMLElement {
196197
private __ctrl!: Ctrl
197-
private __hasAddedPropHandling = false
198198

199199
constructor() {
200200
super()
201201

202+
const self: any = this
202203
const elemConfig = elemConfigByClass.get(this.constructor)!
203204
const { init, patch } = elemConfig.impl
204205
let styles = elemConfig.styles
@@ -232,29 +233,30 @@ class BaseElement extends HTMLElement {
232233
//contentElement.append(document.createElement('span'))
233234
this.shadowRoot!.append(stylesElement, contentElement)
234235

235-
let initialized = false
236+
let rendered = false
236237
let mounted = false
237238
let updated = false
238239
let shallCommit = false
239240
let getContent: () => any // TODO
240241

242+
const onceBeforeMountNotifier = createNotifier()
243+
const onceBeforeUpdateNotifier = createNotifier()
241244
const beforeMountNotifier = createNotifier()
242245
const afterMountNotifier = createNotifier()
243246
const beforeUpdateNotifier = createNotifier()
244247
const afterUpdateNotifier = createNotifier()
245248
const beforeUnmountNotifier = createNotifier()
246-
const onceBeforeUpdateActions: (() => void)[] = []
247249

248250
const ctrl: Ctrl = {
249251
getName: () => this.localName,
250252
getHost: () => this,
251-
isInitialized: () => initialized,
253+
hasRendered: () => rendered,
252254
isMounted: () => mounted,
253255
hasUpdated: () => updated,
256+
onceBeforeMount: onceBeforeMountNotifier.subscribe,
254257
beforeMount: beforeMountNotifier.subscribe,
255258
afterMount: afterMountNotifier.subscribe,
256-
onceBeforeUpdate: (task: () => void) =>
257-
onceBeforeUpdateActions.push(task),
259+
onceBeforeUpdate: onceBeforeUpdateNotifier.subscribe,
258260
beforeUpdate: beforeUpdateNotifier.subscribe,
259261
afterUpdate: afterUpdateNotifier.subscribe,
260262
beforeUnmount: beforeUnmountNotifier.subscribe,
@@ -275,12 +277,10 @@ class BaseElement extends HTMLElement {
275277

276278
const commit = () => {
277279
if (mounted) {
278-
if (onceBeforeUpdateActions.length) {
279-
try {
280-
onceBeforeUpdateActions.forEach((action) => action())
281-
} finally {
282-
onceBeforeUpdateActions.length = 0
283-
}
280+
try {
281+
onceBeforeUpdateNotifier.notify()
282+
} finally {
283+
onceBeforeMountNotifier.clear()
284284
}
285285

286286
beforeUpdateNotifier.notify()
@@ -301,7 +301,7 @@ class BaseElement extends HTMLElement {
301301
interceptions.render
302302
)
303303

304-
initialized = true
304+
rendered = true
305305

306306
if (!mounted) {
307307
mounted = true
@@ -312,27 +312,25 @@ class BaseElement extends HTMLElement {
312312
}
313313
}
314314

315-
;(this as any).connectedCallback = () => {
316-
if (!this.__hasAddedPropHandling) {
317-
addPropHandling(this)
318-
this.__hasAddedPropHandling = true
319-
}
315+
runIntercepted(
316+
() => {
317+
getContent = init(this, ctrl)
318+
},
319+
ctrl,
320+
interceptions.init
321+
)
320322

321-
if (!initialized) {
322-
runIntercepted(
323-
() => {
324-
getContent = init(this, ctrl)
325-
},
326-
ctrl,
327-
interceptions.init
328-
)
323+
self.connectedCallback = () => {
324+
if (!rendered) {
325+
addPropHandling(this)
326+
onceBeforeMountNotifier.notify()
329327
}
330328

331329
beforeMountNotifier.notify()
332-
333330
commit()
334331
}
335-
;(this as any).disconnectedCallback = () => {
332+
333+
self.disconnectedCallback = () => {
336334
beforeUnmountNotifier.notify()
337335
contentElement.innerHTML = ''
338336
}
@@ -381,11 +379,6 @@ function addAttributeHandling(
381379
oldValue: string | null,
382380
value: string | null
383381
) {
384-
if (!this.__hasAddedPropHandling) {
385-
addPropHandling(this)
386-
this.__hasAddedPropHandling = true
387-
}
388-
389382
if (!ignoreAttributeChange) {
390383
const { propName, mapAttrToProp } = propConfigByAttrName.get(
391384
attrName
@@ -409,6 +402,8 @@ function addPropHandling(obj: any) {
409402
let propValue = obj[propName]
410403

411404
Object.defineProperty(obj, propName, {
405+
configurable: true, // TODO!!!!!!!!!!!!!!!!!!!!!!!!!!
406+
412407
get() {
413408
return propValue
414409
},
@@ -466,7 +461,9 @@ function createNotifier() {
466461

467462
return {
468463
subscribe: (subscriber: () => void) => void subscribers.push(subscriber),
469-
notify: () => void (subscribers.length && subscribers.forEach((it) => it()))
464+
notify: () =>
465+
void (subscribers.length && subscribers.forEach((it) => it())),
466+
clear: () => (subscribers.length = 0)
470467
}
471468
}
472469

src/stories/demos/counter-demo.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { component, elem, prop, setMethods, Attrs } from 'js-element'
2-
import { useState } from 'js-element/hooks'
2+
import { useOnInit, useState } from 'js-element/hooks'
33
import { createRef, html, lit, ref } from 'js-element/lit'
44

55
@elem({
@@ -12,6 +12,9 @@ class Counter extends component<{
1212
increment(): void
1313
decrement(): void
1414
}>() {
15+
@prop({ attr: Attrs.number, refl: true })
16+
initialCount = 0
17+
1518
@prop({ attr: Attrs.string, refl: true })
1619
labelText = 'Counter'
1720

@@ -32,6 +35,10 @@ function counterImpl(self: Counter) {
3235
decrement: () => setState('count', (it) => it - 1)
3336
})
3437

38+
useOnInit(() => {
39+
setState('count', self.initialCount)
40+
})
41+
3542
return () => html`
3643
<button ?disabled=${self.disabled} @click=${onClick}>
3744
${self.labelText}: ${state.count}
@@ -56,7 +63,7 @@ function counterDemoImpl() {
5663
return () => html`
5764
<div>
5865
<h3>Counter demo</h3>
59-
<x-counter ${ref(counterRef)}></x-counter>
66+
<x-counter .initialCount=${100} ${ref(counterRef)}></x-counter>
6067
<button @click=${onDecrementClick}>-1</button>
6168
<button @click=${onIncrementClick}>+1</button>
6269
<button @click=${onResetClick}>Reset</button>

0 commit comments

Comments
 (0)