From af1bd7fa1361927d4f5462f891bbbd354831a48c Mon Sep 17 00:00:00 2001 From: lmhcoding <13265878974@163.com> Date: Sun, 20 Sep 2020 16:07:07 +0800 Subject: [PATCH] feat: add useHistory --- src/index.ts | 1 + src/useHistory.ts | 64 +++++++++++++++++++++++++++++++++++++++++++++++ src/util.ts | 8 ++++++ 3 files changed, 73 insertions(+) create mode 100644 src/useHistory.ts create mode 100644 src/util.ts diff --git a/src/index.ts b/src/index.ts index 5a46382..12c433b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,3 +13,4 @@ export * from './useStorage' export * from './useLifecycles' export * from './useInterval' export * from './useHash' +export * from './useHistory' diff --git a/src/useHistory.ts b/src/useHistory.ts new file mode 100644 index 0000000..40d5881 --- /dev/null +++ b/src/useHistory.ts @@ -0,0 +1,64 @@ +import { reactive, toRefs, ToRefs, UnwrapRef } from 'vue' +import { useEvent } from './useEvent' +import { def } from './util' + +type PathMethod = Extract + +function patchHistoryMethod(method: PathMethod): void { + const history = window.history + const origin = history[method] + + def( + history, + method, + function (this: History, state: any) { + const result = origin.apply(this, (arguments as unknown) as Parameters) + const event: any = new Event(method.toLowerCase()) + event.state = state + window.dispatchEvent(event) + return result + }, + true + ) +} + +patchHistoryMethod('pushState') +patchHistoryMethod('replaceState') + +export interface IHistoryState { + state: any + hash: string + search: any + host: string + hostname: string + href: string + origin: string + pathname: string + port: string + protocol: string +} + +function buildState(): IHistoryState { + const { state } = window.history + const { hash, search, host, hostname, href, origin, pathname, port, protocol } = window.location + return { + state, + hash, + search, + host, + hostname, + href, + origin, + pathname, + port, + protocol + } +} + +export function useHistory(): ToRefs { + const state: UnwrapRef = reactive(buildState()) + useEvent('popstate', buildState) + useEvent('pushstate' as any, buildState) + useEvent('replacestate' as any, buildState) + return toRefs(state) +} diff --git a/src/util.ts b/src/util.ts new file mode 100644 index 0000000..6df7ddd --- /dev/null +++ b/src/util.ts @@ -0,0 +1,8 @@ +export function def(obj: T, key: keyof T, val: any, enumerable?: boolean) { + Object.defineProperty(obj, key, { + value: val, + enumerable: !!enumerable, + writable: true, + configurable: true + }) +}