@ithinkdt/core
Version:
iThinkDT Core
177 lines (158 loc) • 6.69 kB
JavaScript
/* 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()),
)
},
},
)
},
})