refactor: use props in stead of attrs

This commit is contained in:
tbitw2549 2024-09-14 18:44:25 +03:00
parent 1ad62a16f5
commit c39bad01e2

View File

@ -5,8 +5,14 @@ import type { AsyncComponentLoader, HydrationStrategy } from 'vue'
export const createLazyIOComponent = (loader: AsyncComponentLoader) => { export const createLazyIOComponent = (loader: AsyncComponentLoader) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
setup (_, { attrs }) { props: {
const comp = defineAsyncComponent({ loader, hydrate: hydrateOnVisible(attrs.hydrate as IntersectionObserverInit | undefined) }) hydrate: {
type: Object,
required: false,
},
},
setup (props, { attrs }) {
const comp = defineAsyncComponent({ loader, hydrate: hydrateOnVisible(props.hydrate as IntersectionObserverInit | undefined) })
const merged = mergeProps(attrs, { 'data-allow-mismatch': '' }) const merged = mergeProps(attrs, { 'data-allow-mismatch': '' })
// TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content. // TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content.
return () => h(comp, merged) return () => h(comp, merged)
@ -18,27 +24,39 @@ export const createLazyIOComponent = (loader: AsyncComponentLoader) => {
export const createLazyNetworkComponent = (loader: AsyncComponentLoader) => { export const createLazyNetworkComponent = (loader: AsyncComponentLoader) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
setup (_, { attrs }) { props: {
hydrate: {
type: Number,
required: false,
},
},
setup (props, { attrs }) {
const merged = mergeProps(attrs, { 'data-allow-mismatch': '' }) const merged = mergeProps(attrs, { 'data-allow-mismatch': '' })
if (attrs.hydrate === 0) { if (props.hydrate === 0) {
const comp = defineAsyncComponent(loader) const comp = defineAsyncComponent(loader)
return () => h(comp, merged) return () => h(comp, merged)
} }
const comp = defineAsyncComponent({ loader, hydrate: hydrateOnIdle(attrs.hydrate as number | undefined) }) const comp = defineAsyncComponent({ loader, hydrate: hydrateOnIdle(props.hydrate) })
// TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content. // TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content.
return () => h(comp, merged) return () => h(comp, merged)
}, },
}) })
} }
type HTMLEvent = keyof HTMLElementEventMap | Array<keyof HTMLElementEventMap>
/* @__NO_SIDE_EFFECTS__ */ /* @__NO_SIDE_EFFECTS__ */
export const createLazyEventComponent = (loader: AsyncComponentLoader) => { export const createLazyEventComponent = (loader: AsyncComponentLoader) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
setup (_, { attrs }) { props: {
const events: HTMLEvent = attrs.hydrate as HTMLEvent ?? 'mouseover' hydrate: {
const comp = defineAsyncComponent({ loader, hydrate: hydrateOnInteraction(events) }) type: [String, Array],
required: false,
default: 'mouseover',
},
},
setup (props, { attrs }) {
// @ts-expect-error Cannot type HTMLElementEventMap in props
const comp = defineAsyncComponent({ loader, hydrate: hydrateOnInteraction(props.hydrate) })
const merged = mergeProps(attrs, { 'data-allow-mismatch': '' }) const merged = mergeProps(attrs, { 'data-allow-mismatch': '' })
// TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content. // TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content.
return () => h(comp, merged) return () => h(comp, merged)
@ -50,9 +68,15 @@ export const createLazyEventComponent = (loader: AsyncComponentLoader) => {
export const createLazyMediaComponent = (loader: AsyncComponentLoader) => { export const createLazyMediaComponent = (loader: AsyncComponentLoader) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
setup (_, { attrs }) { props: {
const mediaQuery = attrs.hydrate as string ?? '(min-width: 1px)' hydrate: {
const comp = defineAsyncComponent({ loader, hydrate: hydrateOnMediaQuery(mediaQuery) }) type: String,
required: false,
default: '(min-width: 1px)',
},
},
setup (props, { attrs }) {
const comp = defineAsyncComponent({ loader, hydrate: hydrateOnMediaQuery(props.hydrate) })
const merged = mergeProps(attrs, { 'data-allow-mismatch': '' }) const merged = mergeProps(attrs, { 'data-allow-mismatch': '' })
// TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content. // TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content.
return () => h(comp, merged) return () => h(comp, merged)
@ -64,20 +88,26 @@ export const createLazyMediaComponent = (loader: AsyncComponentLoader) => {
export const createLazyIfComponent = (loader: AsyncComponentLoader) => { export const createLazyIfComponent = (loader: AsyncComponentLoader) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
setup (_, { attrs }) { props: {
const shouldHydrate = ref(!!(attrs.hydrate ?? true)) hydrate: {
if (shouldHydrate.value) { type: Boolean,
required: false,
default: true,
},
},
setup (props, { attrs }) {
const merged = mergeProps(attrs, { 'data-allow-mismatch': '' })
if (props.hydrate) {
const comp = defineAsyncComponent(loader) const comp = defineAsyncComponent(loader)
const merged = mergeProps(attrs, { 'data-allow-mismatch': '' })
// TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content. // TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content.
return () => h(comp, merged) return () => h(comp, merged)
} }
const strategy: HydrationStrategy = (hydrate) => { const strategy: HydrationStrategy = (hydrate) => {
const unwatch = watch(shouldHydrate, () => hydrate(), { once: true }) const unwatch = watch(() => props.hydrate, () => hydrate(), { once: true })
return () => unwatch() return () => unwatch()
} }
const comp = defineAsyncComponent({ loader, hydrate: strategy }) const comp = defineAsyncComponent({ loader, hydrate: strategy })
return () => h(comp, attrs) return () => h(comp, merged)
}, },
}) })
} }
@ -86,14 +116,21 @@ export const createLazyIfComponent = (loader: AsyncComponentLoader) => {
export const createLazyTimeComponent = (loader: AsyncComponentLoader) => { export const createLazyTimeComponent = (loader: AsyncComponentLoader) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
setup (_, { attrs }) { props: {
hydrate: {
type: Number,
required: false,
default: 2000,
},
},
setup (props, { attrs }) {
const merged = mergeProps(attrs, { 'data-allow-mismatch': '' }) const merged = mergeProps(attrs, { 'data-allow-mismatch': '' })
if (attrs.hydrate === 0) { if (props.hydrate === 0) {
const comp = defineAsyncComponent(loader) const comp = defineAsyncComponent(loader)
return () => h(comp, merged) return () => h(comp, merged)
} }
const strategy: HydrationStrategy = (hydrate) => { const strategy: HydrationStrategy = (hydrate) => {
const id = setTimeout(hydrate, attrs.hydrate as number | undefined ?? 2000) const id = setTimeout(hydrate, props.hydrate)
return () => clearTimeout(id) return () => clearTimeout(id)
} }
const comp = defineAsyncComponent({ loader, hydrate: strategy }) const comp = defineAsyncComponent({ loader, hydrate: strategy })
@ -107,17 +144,22 @@ export const createLazyTimeComponent = (loader: AsyncComponentLoader) => {
export const createLazyPromiseComponent = (loader: AsyncComponentLoader) => { export const createLazyPromiseComponent = (loader: AsyncComponentLoader) => {
return defineComponent({ return defineComponent({
inheritAttrs: false, inheritAttrs: false,
setup (_, { attrs }) { props: {
hydrate: {
type: Promise,
required: false,
},
},
setup (props, { attrs }) {
const merged = mergeProps(attrs, { 'data-allow-mismatch': '' }) const merged = mergeProps(attrs, { 'data-allow-mismatch': '' })
// @ts-expect-error Attributes cannot be typed if (!props.hydrate || typeof props.hydrate.then !== 'function') {
if (!attrs.hydrate || typeof attrs.hydrate.then !== 'function') {
const comp = defineAsyncComponent(loader) const comp = defineAsyncComponent(loader)
// TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content. // TODO: fix hydration mismatches on Vue's side. The data-allow-mismatch is ideally a temporary solution due to Vue's SSR limitation with hydrated content.
return () => h(comp, merged) return () => h(comp, merged)
} }
const strategy: HydrationStrategy = (hydrate) => { const strategy: HydrationStrategy = (hydrate) => {
// @ts-expect-error Attributes cannot be typed // @ts-expect-error TS does not see hydrate as non-null
attrs.hydrate.then(hydrate) props.hydrate.then(hydrate)
return () => {} return () => {}
} }
const comp = defineAsyncComponent({ loader, hydrate: strategy }) const comp = defineAsyncComponent({ loader, hydrate: strategy })