Last active
October 5, 2024 06:14
-
-
Save RyosukeCla/fa340b4fc82bb37bd29a1c6ab2769ad3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect } from 'react'; | |
import { useHistory } from 'react-router-dom'; | |
const prefix = 'vue-router-event'; | |
const vueRouterGoHook = `${prefix}-go`; | |
const vueRouterReplaceHook = `${prefix}-go`; | |
const vueRouterPushHook = `${prefix}-push`; | |
/** | |
* /packages/front で管理されてる vuejs 内で動いている vue-router との integration | |
* vue-router から event が送られてきたらときに、こちらで history api を使用する | |
*/ | |
function VueRouterHook() { | |
const hisotry = useHistory<{ fromVueRouter?: boolean }>(); | |
const onGoHook = (event: CustomEvent<{ n: number }>) => { | |
console.log('[React] onGo', event.detail.n); | |
hisotry.go(event.detail.n); | |
}; | |
const onReplaceHook = (event: CustomEvent<{ location: string }>) => { | |
console.log('[React] onReplace', event.detail.location); | |
hisotry.replace(event.detail.location, { fromVueRouter: true }); | |
}; | |
const onPushHook = (event: CustomEvent<{ location: string }>) => { | |
console.log('[React] onPush', event.detail.location); | |
hisotry.push(event.detail.location, { fromVueRouter: true }); | |
}; | |
useEffect(() => { | |
window.addEventListener(vueRouterGoHook, onGoHook as any); | |
window.addEventListener(vueRouterReplaceHook, onReplaceHook as any); | |
window.addEventListener(vueRouterPushHook, onPushHook as any); | |
/** | |
* vue router に event を送る。 | |
*/ | |
hisotry.listen((location, action) => { | |
/** | |
* push, replace かつ、vue router 起因の場合は skip する。 | |
*/ | |
if (action !== 'POP' && location.state?.fromVueRouter) return; | |
console.log('[React] dispatch', location.pathname + location.search + location.hash); | |
window.dispatchEvent( | |
new CustomEvent('react-router-event-transition-to', { | |
detail: { | |
location: location.pathname + location.search + location.hash, | |
}, | |
}) | |
); | |
}); | |
return () => { | |
window.removeEventListener(vueRouterGoHook, onGoHook as any); | |
window.removeEventListener(vueRouterReplaceHook, onReplaceHook as any); | |
window.removeEventListener(vueRouterPushHook, onPushHook as any); | |
} | |
}, []); | |
return null; | |
} | |
export default VueRouterHook; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Router, { Route, RawLocation, RouterOptions } from 'vue-router'; | |
/** | |
* from | |
* https://github.com/vuejs/vue-router/blob/90cd2690d59c6bd56e5bc12b5b752166a1d35e98/src/history/html5.js#L39-L41 | |
*/ | |
type ExposedRouter = Router & { | |
match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route; | |
} | |
type BaseHistory = { | |
router: ExposedRouter; | |
base: string; | |
current: Route; | |
pending?: Route; | |
cb: (r: Route) => void; | |
ready: boolean; | |
readyCbs: Array<Function>; | |
readyErrorCbs: Array<Function>; | |
errorCbs: Array<Function>; | |
listen: (cb: Function) => void; | |
onReady: (cb: Function, errorCb?: Function) => void; | |
onError: (errorCb: Function) => void; | |
transitionTo: (location: RawLocation, onComplete?: (route: Route) => void, onAbort?: Function) => void; | |
confirmTransition: (route: Route, onComplete: Function, onAbort?: Function) => void; | |
updateRoute: (route: Route) => void; | |
} | |
type SubHistory = BaseHistory & { | |
push: (location: RawLocation, onComplete?: Function, onAbort?: Function) => void; | |
go: (n: number) => void; | |
replace: (location: RawLocation, onComplete?: Function, onAbort?: Function) => void; | |
getCurrentLocation: () => string; | |
ensureURL: (push?: boolean) => void; | |
} | |
type AbstractHistory = SubHistory & { | |
stack: string[]; | |
index: number; // default := -1; | |
} | |
type ExposedVueRouter = Router & { | |
history: AbstractHistory; | |
options: RouterOptions; | |
}; | |
function hackHistoryInVueRouter(vueRouter: ExposedVueRouter) { | |
/** | |
* react router の変更が走ったら、vue router で transition する。 | |
*/ | |
const onReactRouterEventTransitionTo = (event: CustomEvent<{ location: string }>) => { | |
console.log('[Vue] onTransitionTo', event.detail.location); | |
vueRouter.history.transitionTo(event.detail.location, (route) => { | |
console.log('[Vue] transitioned', event.detail.location, route.name); | |
}, (err: any) => { | |
if (err) console.log(`[Vue] error, ${err}`); | |
}); | |
} | |
window.addEventListener('react-router-event-transition-to', onReactRouterEventTransitionTo as any); | |
/** | |
* history の動作を変更する | |
*/ | |
vueRouter.history.getCurrentLocation = () => { | |
return window.location.pathname + window.location.search + window.location.hash | |
} | |
vueRouter.history.go = (n) => { | |
dispatch('go', { n }); | |
} | |
vueRouter.history.push = (location, onComplete, onAbort) => { | |
vueRouter.history.transitionTo( | |
location, | |
(route) => { | |
dispatch('push', { location: route.fullPath }); | |
onComplete && onComplete(route); | |
}, | |
onAbort | |
); | |
} | |
vueRouter.history.replace = (location, onComplete, onAbort) => { | |
vueRouter.history.transitionTo( | |
location, | |
(route) => { | |
dispatch('replace', { location: route.fullPath }); | |
onComplete && onComplete(route); | |
}, | |
onAbort, | |
); | |
} | |
/** | |
* https://github.com/vuejs/vue-router/blob/90cd2690d59c6bd56e5bc12b5b752166a1d35e98/src/index.js#L102 | |
* abstract だと初期化されないので、ここでする。 | |
*/ | |
vueRouter.history.transitionTo( | |
vueRouter.history.getCurrentLocation() | |
); | |
} | |
function dispatch(eventName: 'go' | 'replace' | 'push', detail: any) { | |
window.dispatchEvent(new CustomEvent(`vue-router-event-${eventName}`, { | |
detail: detail, | |
})); | |
} | |
export { | |
hackHistoryInVueRouter | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment