UNPKG

@ithinkdt/core

Version:

iThinkDT Core

177 lines (158 loc) 6.69 kB
/* eslint-disable unicorn/filename-case */ import { defineComponent, markRaw, toRaw, watch, ref, provide, h, getCurrentInstance, shallowRef, KeepAlive, Transition, Suspense, onMounted, onUnmounted, onActivated, onDeactivated, } from 'vue' import { watchDebounced } from '@vueuse/core' import { RouterView, onBeforeRouteLeave } from 'vue-router' import { useTheme, PageTabInjection } from './plugin' import { usePageTab } from './page-tab/use-page-tab' const _c = Symbol() const _v = Symbol() const _proxy = Symbol() export const DtLayoutView = defineComponent({ name: 'DtLayoutView', props: { transition: { type: Object, required: false, default: () => ({}), }, suspense: { type: Object, required: false, default: () => ({}), }, }, setup(props) { const theme = useTheme() const ErrorView = theme.Error const includes = ref([]) watchDebounced( () => theme.pages, async () => { includes.value = theme.pages .filter((tab) => tab.keepAlive && !tab.reloading) .map((tab) => `Route@${tab.keepAliveKey}`) }, { immediate: true, flush: 'pre' }, ) let tab watch( () => theme.currentPage, (curr) => { tab = curr ? toRaw(curr) : undefined if (tab) { tab[_proxy] = curr const _tab = theme.pages.find((t) => t.keepAliveKey === tab.keepAliveKey) tab[_c] = _tab?.[_c] } }, { immediate: true, flush: 'pre' }, ) let _resolve, _timer const onLeave = () => { _resolve?.() clearTimeout(_timer) } return () => h( RouterView, {}, { default({ Component }) { if (!Component) return let $content const _tab = tab if (_tab) { _tab[_v] = Component if (!_tab[_c]) { _tab[_c] = markRaw( defineComponent({ name: `Route@${_tab.keepAliveKey}`, setup() { const inst = getCurrentInstance() inst._tab = shallowRef(_tab?.[_proxy]) provide(PageTabInjection, inst._tab) if (!_tab?.error) { onBeforeRouteLeave((_, from) => { if (_tab) _tab.path = from.fullPath }) } if (import.meta.env.DEV) { onMounted(() => { console.debug(`[router] '${_tab?.key}' mounted.`) }) onActivated(() => { console.debug(`[router] '${_tab?.key}' activated.`) }) onDeactivated(() => { console.debug(`[router] '${_tab?.key}' deactivated.`) }) onUnmounted(() => { console.debug(`[router] '${_tab?.key}' unmounted.`) }) } onMounted(() => { usePageTab(undefined, { priority: 'low' }) }) return () => { const tabRaw = _tab?.[_proxy] inst._tab.value = _tab?.[_proxy] return tabRaw?.error ? h(ErrorView, { type: tabRaw.error === '403' ? '403' : '500' }) : tabRaw?.reloading ? undefined : _tab?.[_v] } }, }), ) } $content = () => { return h(_tab[_c], { key: _tab?.keepAliveKey, onClose: () => { theme.closePage(_tab) }, }) } } else { $content = Component ? () => h(ErrorView, { type: '500' }) : () => h('span') } const content = () => h(Suspense, props.suspense, $content) if (!theme.multiTab) return content() return h( Transition, { ...props.transition, onBeforeEnter: () => { theme.transition = new Promise((resolve) => (_resolve = resolve)) _timer = setTimeout(() => { _resolve?.() }, 800) }, onEnterCancelled: onLeave, onAfterEnter: onLeave, }, () => h(KeepAlive, { include: includes.value }, content()), ) }, }, ) }, })