Skip to content

Commit 68a86ba

Browse files
author
Simon he
committed
refactor: add mount to refactor code
1 parent daf569d commit 68a86ba

File tree

10 files changed

+79
-189
lines changed

10 files changed

+79
-189
lines changed

src/addEventListener.ts

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
import { isStr } from './isStr'
2-
import { animationFrameWrapper } from './animationFrameWrapper'
3-
import { findElement } from './findElement'
1+
import { mount } from './mount'
42

53
export function addEventListener(target: Window | Document | Element | string, eventName: string, callback: (e: any) => void, useCapture?: boolean | AddEventListenerOptions, autoRemove?: boolean): (() => void) {
6-
let isMounted = false
7-
let hasMounted = false
84
let stopped = false
95
let stop: () => void
106
let animationStop: (() => void)
@@ -21,29 +17,11 @@ export function addEventListener(target: Window | Document | Element | string, e
2117
if (autoRemove)
2218
stop()
2319
}
24-
update()
25-
window.addEventListener('DOMContentLoaded', () => {
26-
update()
27-
if (stopped)
28-
stop?.()
29-
})
3020

3121
window.onunload = () => stop?.()
32-
if (eventName === 'DOMContentLoaded')
33-
animationStop = animationFrameWrapper(callback, 0, true)
34-
else
35-
animationFrameWrapper(update, 0, true)
3622

37-
function update() {
38-
if (hasMounted)
39-
return
40-
if (isStr(target))
41-
target = findElement(target) as Element || target
42-
if (!isMounted && isStr(target))
43-
return isMounted = true
44-
else if (isStr(target))
45-
throw new Error(`${target} is not a Element`)
46-
const originCall = (target as unknown as any)?.[eventName]
23+
mount(target, (target) => {
24+
const originCall = (target as any)?.[eventName]
4725
const eventFunction = (e: Event) => {
4826
try {
4927
const isRawClick = originCall && originCall.toString() === 'function click() { [native code] }'
@@ -59,10 +37,10 @@ export function addEventListener(target: Window | Document | Element | string, e
5937
stop = () => (target as Element).removeEventListener(eventName, eventFunction, useCapture)
6038
if (stopped)
6139
stop?.()
62-
hasMounted = true
63-
}
40+
})
6441
return () => {
65-
if (!stop) return stopped = true
42+
if (!stop)
43+
return stopped = true
6644
stop?.()
6745
}
6846
}

src/dragEvent.ts

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,44 @@
11
import { getDevice } from './getDevice'
2-
import { isStr } from './isStr'
32
import { addEventListener } from './addEventListener'
43
import type { DragEvent } from './types'
5-
import { findElement } from './findElement'
4+
import { mount } from './mount'
65

76
export function dragEvent(target: HTMLElement | string, options: DragEvent = {}, trigger?: boolean) {
8-
let isMounted = false
9-
let hasMounted = false
107
const { os } = getDevice()
118
const isPhone = os === 'ios' || os === 'android'
129
const stop: (() => void)[] = []
13-
function update() {
14-
if (hasMounted)
15-
return
16-
if (isStr(target))
17-
target = findElement(target) || target
18-
if (!isMounted && isStr(target))
19-
return isMounted = true
20-
else if (isStr(target))
21-
throw new Error(`${target} is not a HTMLElement`)
10+
let isStopped = false
11+
mount(target, (target) => {
2212
let down = false
2313
if (isPhone) {
24-
stop.push(addEventListener(target as HTMLElement, 'touchstart', (e: any) => {
14+
stop.push(addEventListener(target, 'touchstart', (e: any) => {
2515
options.dragStart && options.dragStart(wrapperE(e))
2616
}, false))
27-
options.dragMove && stop.push(addEventListener(target as HTMLElement, 'touchmove', (e: any) => {
17+
options.dragMove && stop.push(addEventListener(target, 'touchmove', (e: any) => {
2818
if (!trigger || down)
2919
options.dragMove?.(wrapperE(e))
3020
}, false))
31-
options.dragEnd && stop.push(addEventListener(target as HTMLElement, 'touchend', (e: any) => {
21+
options.dragEnd && stop.push(addEventListener(target, 'touchend', (e: any) => {
3222
options.dragEnd?.(wrapperE(e))
3323
down = false
3424
}, false))
35-
}
25+
}
3626
else {
37-
stop.push(addEventListener(target as HTMLElement, 'mousedown', (e: any) => {
27+
stop.push(addEventListener(target, 'mousedown', (e: any) => {
3828
down = true
3929
options.dragStart && options.dragStart(e)
4030
}, false))
41-
options.dragMove && stop.push(addEventListener(target as HTMLElement, 'mousemove', (e: any) => {
31+
options.dragMove && stop.push(addEventListener(target, 'mousemove', (e: any) => {
4232
if (!trigger || down)
4333
options.dragMove?.(e)
4434
}, false))
45-
options.dragEnd && stop.push(addEventListener(target as HTMLElement, 'mouseup', (e: any) => {
35+
options.dragEnd && stop.push(addEventListener(target, 'mouseup', (e: any) => {
4636
options.dragEnd?.(e)
4737
down = false
4838
}, false))
4939
}
50-
hasMounted = true
40+
if (isStopped)
41+
stop.forEach(stop => stop())
5142
function wrapperE(e: any) {
5243
const { clientX, clientY, pageX, pageY, screenX, screenY } = e?.changedTouches[0]
5344
e.clientX = clientX
@@ -58,10 +49,10 @@ export function dragEvent(target: HTMLElement | string, options: DragEvent = {},
5849
e.screenY = screenY
5950
return e
6051
}
61-
}
62-
update()
63-
addEventListener(document, 'DOMContentLoaded', update)
52+
})
6453
return () => {
54+
if (!stop.length)
55+
return isStopped = true
6556
stop.forEach(cb => cb?.())
6657
}
6758
}

src/insertElement.ts

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,5 @@
1-
import { addEventListener } from './addEventListener'
2-
import { findElement } from './findElement'
3-
import { isStr } from './isStr'
1+
import { mount } from './mount'
42

53
export function insertElement(parent: HTMLElement | string, element: HTMLElement | string, target?: HTMLElement | null): void {
6-
let isMounted = false
7-
let hasMounted = false
8-
update()
9-
addEventListener(document, 'DOMContentLoaded', update)
10-
function update() {
11-
if (hasMounted)
12-
return
13-
if (isStr(parent))
14-
parent = findElement(parent) || parent
15-
if (isStr(element))
16-
element = findElement(element) || element
17-
if (!isMounted && (isStr(parent) || isStr(element)))
18-
return isMounted = true
19-
if (isStr(parent))
20-
throw new Error(`${parent} is not a HTMLElement`)
21-
if (isStr(element))
22-
throw new Error(`${element} is not a HTMLElement`);
23-
(parent as HTMLElement).insertBefore(element as HTMLElement, target === undefined ? (parent as HTMLElement).firstChild : target)
24-
hasMounted = true
25-
}
4+
mount(parent, element, (parent, element) => (parent as HTMLElement).insertBefore(element as HTMLElement, target === undefined ? (parent as HTMLElement).firstChild : target))
265
}

src/mount.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { findElement } from './findElement'
2+
import { isStr } from './isStr'
3+
4+
type MountArgs = [...Array<string | Element | Window | Document | ParentNode>, (...elements: Element[]) => void]
5+
export function mount(...args: MountArgs): void {
6+
const len = args.length
7+
const params = [...args]
8+
const elements = params.slice(0, len - 1)
9+
const callback = params.slice(-1)[0] as unknown as (...elements: Element[]) => void
10+
let isMounted = false
11+
let hasMounted = false
12+
update()
13+
document.addEventListener('DOMContentLoaded', update)
14+
setTimeout(() => document.removeEventListener('DOMContentLoaded', update))
15+
function update() {
16+
if (hasMounted)
17+
return
18+
elements.forEach((element, index) => isStr(element) && (elements[index] = findElement(element) || element))
19+
if (!isMounted && elements.some(isStr))
20+
return isMounted = true
21+
if (elements.some(isStr))
22+
throw new Error(`${elements.filter(isStr).join(', ')} is not a HTMLElement`)
23+
callback?.(...elements as Element[])
24+
hasMounted = true
25+
}
26+
}

src/useClick.ts

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,14 @@
1-
import { isStr } from './isStr'
21
import { addEventListener } from './addEventListener'
3-
import { findElement } from './findElement'
2+
import { mount } from './mount'
43

54
export function useClick(target: string | HTMLElement, callback: () => void) {
6-
let isMounted = false
7-
let hasMounted = false
85
let stop: () => void
96
let stopped = false
10-
11-
update()
12-
addEventListener(window, 'DOMContentLoaded', update)
13-
14-
function update() {
15-
if (hasMounted)
16-
return
17-
if (isStr(target))
18-
target = findElement(target) || target
19-
if (!isMounted && isStr(target))
20-
return isMounted = true
21-
else if (isStr(target))
22-
throw new Error(`${target} is not a Element`)
23-
stop = addEventListener(target, 'click', callback)
7+
mount(target, (target) => {
8+
stop = addEventListener(target as Element, 'click', callback)
249
if (stopped)
2510
stop?.()
26-
hasMounted = true
27-
}
11+
})
2812
return () => {
2913
if (!stop)
3014
return stopped = true

src/useElementBounding.ts

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,7 @@
11
import { addEventListener } from './addEventListener'
2-
import { findElement } from './findElement'
3-
import { isStr } from './isStr'
4-
2+
import { mount } from './mount'
53
export function useElementBounding(element: Element | string, callback: (rect: DOMRect) => void) {
6-
let isMounted = false
7-
let hasMounted = false
8-
update()
9-
addEventListener(document, 'DOMContentLoaded', update)
10-
return addEventListener(window, 'scroll', update)
11-
function update() {
12-
if (hasMounted)
13-
return
14-
if (isStr(element))
15-
element = findElement(element) || element
16-
if (!isMounted && isStr(element))
17-
return isMounted = true
18-
if (isStr(element))
19-
throw new Error(`${element} is not a Element`)
20-
callback?.((element as Element).getBoundingClientRect())
21-
hasMounted = true
22-
}
4+
mount(element, el => callback?.((element = el).getBoundingClientRect()))
5+
return addEventListener(window, 'scroll', () => callback?.((element as Element).getBoundingClientRect()))
236
}
7+

src/useFocus.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,5 @@
11
import { findElement } from './findElement'
2-
import { isStr } from './isStr'
3-
import { addEventListener } from './addEventListener'
4-
2+
import { mount } from './mount'
53
export function useFocus(target: string | HTMLElement) {
6-
let isMounted = false
7-
let hasMounted = false
8-
update()
9-
addEventListener(document, 'DOMContentLoaded', update)
10-
function update() {
11-
if (hasMounted)
12-
return
13-
if (isStr(target))
14-
target = findElement(target) as HTMLElement || target
15-
if (!isMounted && isStr(target))
16-
return isMounted = true
17-
else if (isStr(target))
18-
throw new Error(`${target} is not a Element`)
19-
findElement('input', target.parentElement!)?.focus()
20-
hasMounted = true
21-
}
4+
mount(target, target => findElement('input', target.parentElement!)?.focus())
225
}

src/useHover.ts

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
1-
import { findElement } from './findElement'
2-
import { isStr } from './isStr'
31
import { addEventListener } from './addEventListener'
2+
import { mount } from './mount'
43

5-
export function useHover(target: string | HTMLElement, callback: (isHover: boolean) => void) {
6-
let hasMounted = false
7-
let isMounted = false
8-
update()
9-
addEventListener(document, 'DOMContentLoaded', update)
10-
11-
function update() {
12-
if (hasMounted)
13-
return
14-
if (isStr(target))
15-
target = findElement(target) as HTMLElement || target
16-
if (!isMounted && isStr(target))
17-
return isMounted = true
18-
else if (isStr(target))
19-
throw new Error(`${target} is not a Element`)
20-
addEventListener(target, 'mouseenter', () => callback(true))
21-
addEventListener(target, 'mouseleave', () => callback(false))
22-
hasMounted = true
4+
export function useHover(target: string | HTMLElement, callback: (isHover: boolean) => void): () => void {
5+
let stopped = false
6+
const stop: (() => void)[] = []
7+
mount(target, (target) => {
8+
stop.push(addEventListener(target, 'mouseenter', () => callback(true)))
9+
stop.push(addEventListener(target, 'mouseleave', () => callback(false)))
10+
if (stopped)
11+
stop.forEach(stop => stop())
12+
})
13+
return () => {
14+
if (!stop.length)
15+
return stopped = true
16+
stop.forEach(fn => fn())
2317
}
2418
}

src/useMutationObserver.ts

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,17 @@
1-
import { isStr } from './isStr'
2-
import { addEventListener } from './addEventListener'
31
import type { MutationObserverInit } from './types'
4-
import { findElement } from './findElement'
2+
import { mount } from './mount'
53
export function useMutationObserver(element: Element | string | ParentNode | null, callback: MutationCallback, options: MutationObserverInit = {}) {
6-
if (!element)
4+
if (!element)
75
return
8-
let isMounted = false
9-
let hasMounted = false
106
let stopped = false
117
let stop: () => void
12-
13-
update()
14-
addEventListener(document, 'DOMContentLoaded', update)
15-
function update() {
16-
if (hasMounted)
17-
return
18-
if (isStr(element))
19-
element = findElement(element) || element
20-
if (!isMounted && isStr(element))
21-
return isMounted = true
22-
else if (isStr(element))
23-
throw new Error(`${element} is not a Element`)
8+
mount(element, (element) => {
249
const mutationObserver = new MutationObserver(callback)
2510
mutationObserver.observe(element as Element, options)
2611
stop = () => mutationObserver.disconnect()
27-
hasMounted = true
2812
if (stopped)
2913
stop()
30-
}
14+
})
3115
return () => {
3216
if (!stop)
3317
return stopped = true

0 commit comments

Comments
 (0)