Skip to content

Commit

Permalink
refactor: add mount to refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon he committed Oct 14, 2022
1 parent daf569d commit 68a86ba
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 189 deletions.
34 changes: 6 additions & 28 deletions src/addEventListener.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { isStr } from './isStr'
import { animationFrameWrapper } from './animationFrameWrapper'
import { findElement } from './findElement'
import { mount } from './mount'

export function addEventListener(target: Window | Document | Element | string, eventName: string, callback: (e: any) => void, useCapture?: boolean | AddEventListenerOptions, autoRemove?: boolean): (() => void) {
let isMounted = false
let hasMounted = false
let stopped = false
let stop: () => void
let animationStop: (() => void)
Expand All @@ -21,29 +17,11 @@ export function addEventListener(target: Window | Document | Element | string, e
if (autoRemove)
stop()
}
update()
window.addEventListener('DOMContentLoaded', () => {
update()
if (stopped)
stop?.()
})

window.onunload = () => stop?.()
if (eventName === 'DOMContentLoaded')
animationStop = animationFrameWrapper(callback, 0, true)
else
animationFrameWrapper(update, 0, true)

function update() {
if (hasMounted)
return
if (isStr(target))
target = findElement(target) as Element || target
if (!isMounted && isStr(target))
return isMounted = true
else if (isStr(target))
throw new Error(`${target} is not a Element`)
const originCall = (target as unknown as any)?.[eventName]
mount(target, (target) => {
const originCall = (target as any)?.[eventName]
const eventFunction = (e: Event) => {
try {
const isRawClick = originCall && originCall.toString() === 'function click() { [native code] }'
Expand All @@ -59,10 +37,10 @@ export function addEventListener(target: Window | Document | Element | string, e
stop = () => (target as Element).removeEventListener(eventName, eventFunction, useCapture)
if (stopped)
stop?.()
hasMounted = true
}
})
return () => {
if (!stop) return stopped = true
if (!stop)
return stopped = true
stop?.()
}
}
39 changes: 15 additions & 24 deletions src/dragEvent.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,44 @@
import { getDevice } from './getDevice'
import { isStr } from './isStr'
import { addEventListener } from './addEventListener'
import type { DragEvent } from './types'
import { findElement } from './findElement'
import { mount } from './mount'

export function dragEvent(target: HTMLElement | string, options: DragEvent = {}, trigger?: boolean) {
let isMounted = false
let hasMounted = false
const { os } = getDevice()
const isPhone = os === 'ios' || os === 'android'
const stop: (() => void)[] = []
function update() {
if (hasMounted)
return
if (isStr(target))
target = findElement(target) || target
if (!isMounted && isStr(target))
return isMounted = true
else if (isStr(target))
throw new Error(`${target} is not a HTMLElement`)
let isStopped = false
mount(target, (target) => {
let down = false
if (isPhone) {
stop.push(addEventListener(target as HTMLElement, 'touchstart', (e: any) => {
stop.push(addEventListener(target, 'touchstart', (e: any) => {
options.dragStart && options.dragStart(wrapperE(e))
}, false))
options.dragMove && stop.push(addEventListener(target as HTMLElement, 'touchmove', (e: any) => {
options.dragMove && stop.push(addEventListener(target, 'touchmove', (e: any) => {
if (!trigger || down)
options.dragMove?.(wrapperE(e))
}, false))
options.dragEnd && stop.push(addEventListener(target as HTMLElement, 'touchend', (e: any) => {
options.dragEnd && stop.push(addEventListener(target, 'touchend', (e: any) => {
options.dragEnd?.(wrapperE(e))
down = false
}, false))
}
}
else {
stop.push(addEventListener(target as HTMLElement, 'mousedown', (e: any) => {
stop.push(addEventListener(target, 'mousedown', (e: any) => {
down = true
options.dragStart && options.dragStart(e)
}, false))
options.dragMove && stop.push(addEventListener(target as HTMLElement, 'mousemove', (e: any) => {
options.dragMove && stop.push(addEventListener(target, 'mousemove', (e: any) => {
if (!trigger || down)
options.dragMove?.(e)
}, false))
options.dragEnd && stop.push(addEventListener(target as HTMLElement, 'mouseup', (e: any) => {
options.dragEnd && stop.push(addEventListener(target, 'mouseup', (e: any) => {
options.dragEnd?.(e)
down = false
}, false))
}
hasMounted = true
if (isStopped)
stop.forEach(stop => stop())
function wrapperE(e: any) {
const { clientX, clientY, pageX, pageY, screenX, screenY } = e?.changedTouches[0]
e.clientX = clientX
Expand All @@ -58,10 +49,10 @@ export function dragEvent(target: HTMLElement | string, options: DragEvent = {},
e.screenY = screenY
return e
}
}
update()
addEventListener(document, 'DOMContentLoaded', update)
})
return () => {
if (!stop.length)
return isStopped = true
stop.forEach(cb => cb?.())
}
}
25 changes: 2 additions & 23 deletions src/insertElement.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,5 @@
import { addEventListener } from './addEventListener'
import { findElement } from './findElement'
import { isStr } from './isStr'
import { mount } from './mount'

export function insertElement(parent: HTMLElement | string, element: HTMLElement | string, target?: HTMLElement | null): void {
let isMounted = false
let hasMounted = false
update()
addEventListener(document, 'DOMContentLoaded', update)
function update() {
if (hasMounted)
return
if (isStr(parent))
parent = findElement(parent) || parent
if (isStr(element))
element = findElement(element) || element
if (!isMounted && (isStr(parent) || isStr(element)))
return isMounted = true
if (isStr(parent))
throw new Error(`${parent} is not a HTMLElement`)
if (isStr(element))
throw new Error(`${element} is not a HTMLElement`);
(parent as HTMLElement).insertBefore(element as HTMLElement, target === undefined ? (parent as HTMLElement).firstChild : target)
hasMounted = true
}
mount(parent, element, (parent, element) => (parent as HTMLElement).insertBefore(element as HTMLElement, target === undefined ? (parent as HTMLElement).firstChild : target))
}
26 changes: 26 additions & 0 deletions src/mount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { findElement } from './findElement'
import { isStr } from './isStr'

type MountArgs = [...Array<string | Element | Window | Document | ParentNode>, (...elements: Element[]) => void]
export function mount(...args: MountArgs): void {
const len = args.length
const params = [...args]
const elements = params.slice(0, len - 1)
const callback = params.slice(-1)[0] as unknown as (...elements: Element[]) => void
let isMounted = false
let hasMounted = false
update()
document.addEventListener('DOMContentLoaded', update)
setTimeout(() => document.removeEventListener('DOMContentLoaded', update))
function update() {
if (hasMounted)
return
elements.forEach((element, index) => isStr(element) && (elements[index] = findElement(element) || element))
if (!isMounted && elements.some(isStr))
return isMounted = true
if (elements.some(isStr))
throw new Error(`${elements.filter(isStr).join(', ')} is not a HTMLElement`)
callback?.(...elements as Element[])
hasMounted = true
}
}
24 changes: 4 additions & 20 deletions src/useClick.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,14 @@
import { isStr } from './isStr'
import { addEventListener } from './addEventListener'
import { findElement } from './findElement'
import { mount } from './mount'

export function useClick(target: string | HTMLElement, callback: () => void) {
let isMounted = false
let hasMounted = false
let stop: () => void
let stopped = false

update()
addEventListener(window, 'DOMContentLoaded', update)

function update() {
if (hasMounted)
return
if (isStr(target))
target = findElement(target) || target
if (!isMounted && isStr(target))
return isMounted = true
else if (isStr(target))
throw new Error(`${target} is not a Element`)
stop = addEventListener(target, 'click', callback)
mount(target, (target) => {
stop = addEventListener(target as Element, 'click', callback)
if (stopped)
stop?.()
hasMounted = true
}
})
return () => {
if (!stop)
return stopped = true
Expand Down
24 changes: 4 additions & 20 deletions src/useElementBounding.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,7 @@
import { addEventListener } from './addEventListener'
import { findElement } from './findElement'
import { isStr } from './isStr'

import { mount } from './mount'
export function useElementBounding(element: Element | string, callback: (rect: DOMRect) => void) {
let isMounted = false
let hasMounted = false
update()
addEventListener(document, 'DOMContentLoaded', update)
return addEventListener(window, 'scroll', update)
function update() {
if (hasMounted)
return
if (isStr(element))
element = findElement(element) || element
if (!isMounted && isStr(element))
return isMounted = true
if (isStr(element))
throw new Error(`${element} is not a Element`)
callback?.((element as Element).getBoundingClientRect())
hasMounted = true
}
mount(element, el => callback?.((element = el).getBoundingClientRect()))
return addEventListener(window, 'scroll', () => callback?.((element as Element).getBoundingClientRect()))
}

21 changes: 2 additions & 19 deletions src/useFocus.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
import { findElement } from './findElement'
import { isStr } from './isStr'
import { addEventListener } from './addEventListener'

import { mount } from './mount'
export function useFocus(target: string | HTMLElement) {
let isMounted = false
let hasMounted = false
update()
addEventListener(document, 'DOMContentLoaded', update)
function update() {
if (hasMounted)
return
if (isStr(target))
target = findElement(target) as HTMLElement || target
if (!isMounted && isStr(target))
return isMounted = true
else if (isStr(target))
throw new Error(`${target} is not a Element`)
findElement('input', target.parentElement!)?.focus()
hasMounted = true
}
mount(target, target => findElement('input', target.parentElement!)?.focus())
}
34 changes: 14 additions & 20 deletions src/useHover.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import { findElement } from './findElement'
import { isStr } from './isStr'
import { addEventListener } from './addEventListener'
import { mount } from './mount'

export function useHover(target: string | HTMLElement, callback: (isHover: boolean) => void) {
let hasMounted = false
let isMounted = false
update()
addEventListener(document, 'DOMContentLoaded', update)

function update() {
if (hasMounted)
return
if (isStr(target))
target = findElement(target) as HTMLElement || target
if (!isMounted && isStr(target))
return isMounted = true
else if (isStr(target))
throw new Error(`${target} is not a Element`)
addEventListener(target, 'mouseenter', () => callback(true))
addEventListener(target, 'mouseleave', () => callback(false))
hasMounted = true
export function useHover(target: string | HTMLElement, callback: (isHover: boolean) => void): () => void {
let stopped = false
const stop: (() => void)[] = []
mount(target, (target) => {
stop.push(addEventListener(target, 'mouseenter', () => callback(true)))
stop.push(addEventListener(target, 'mouseleave', () => callback(false)))
if (stopped)
stop.forEach(stop => stop())
})
return () => {
if (!stop.length)
return stopped = true
stop.forEach(fn => fn())
}
}
24 changes: 4 additions & 20 deletions src/useMutationObserver.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,17 @@
import { isStr } from './isStr'
import { addEventListener } from './addEventListener'
import type { MutationObserverInit } from './types'
import { findElement } from './findElement'
import { mount } from './mount'
export function useMutationObserver(element: Element | string | ParentNode | null, callback: MutationCallback, options: MutationObserverInit = {}) {
if (!element)
if (!element)
return
let isMounted = false
let hasMounted = false
let stopped = false
let stop: () => void

update()
addEventListener(document, 'DOMContentLoaded', update)
function update() {
if (hasMounted)
return
if (isStr(element))
element = findElement(element) || element
if (!isMounted && isStr(element))
return isMounted = true
else if (isStr(element))
throw new Error(`${element} is not a Element`)
mount(element, (element) => {
const mutationObserver = new MutationObserver(callback)
mutationObserver.observe(element as Element, options)
stop = () => mutationObserver.disconnect()
hasMounted = true
if (stopped)
stop()
}
})
return () => {
if (!stop)
return stopped = true
Expand Down
Loading

0 comments on commit 68a86ba

Please sign in to comment.