mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-28 20:03:11 +00:00
wip: review work
This commit is contained in:
parent
23d0b8e4c8
commit
8c522836ed
@ -14,7 +14,7 @@ import { onNuxtReady } from '../composables/ready'
|
|||||||
import { navigateTo, useRouter } from '../composables/router'
|
import { navigateTo, useRouter } from '../composables/router'
|
||||||
import { useNuxtApp, useRuntimeConfig } from '../nuxt'
|
import { useNuxtApp, useRuntimeConfig } from '../nuxt'
|
||||||
import { cancelIdleCallback, requestIdleCallback } from '../compat/idle-callback'
|
import { cancelIdleCallback, requestIdleCallback } from '../compat/idle-callback'
|
||||||
import { useObserver } from '../utils'
|
import type { ObserveFn, CallbackFn } from '../utils'
|
||||||
|
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { nuxtLinkDefaults } from '#build/nuxt.config.mjs'
|
import { nuxtLinkDefaults } from '#build/nuxt.config.mjs'
|
||||||
@ -437,6 +437,47 @@ function applyTrailingSlashBehavior (to: string, trailingSlash: NuxtLinkOptions[
|
|||||||
|
|
||||||
// --- Prefetching utils ---
|
// --- Prefetching utils ---
|
||||||
|
|
||||||
|
function useObserver (): { observe: ObserveFn } | undefined {
|
||||||
|
if (import.meta.server) { return }
|
||||||
|
|
||||||
|
const nuxtApp = useNuxtApp()
|
||||||
|
if (nuxtApp._observer) {
|
||||||
|
return nuxtApp._observer
|
||||||
|
}
|
||||||
|
|
||||||
|
let observer: IntersectionObserver | null = null
|
||||||
|
|
||||||
|
const callbacks = new Map<Element, CallbackFn>()
|
||||||
|
|
||||||
|
const observe: ObserveFn = (element, callback) => {
|
||||||
|
if (!observer) {
|
||||||
|
observer = new IntersectionObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
const callback = callbacks.get(entry.target)
|
||||||
|
const isVisible = entry.isIntersecting || entry.intersectionRatio > 0
|
||||||
|
if (isVisible && callback) { callback() }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
callbacks.set(element, callback)
|
||||||
|
observer.observe(element)
|
||||||
|
return () => {
|
||||||
|
callbacks.delete(element)
|
||||||
|
observer!.unobserve(element)
|
||||||
|
if (callbacks.size === 0) {
|
||||||
|
observer!.disconnect()
|
||||||
|
observer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const _observer = nuxtApp._observer = {
|
||||||
|
observe
|
||||||
|
}
|
||||||
|
|
||||||
|
return _observer
|
||||||
|
}
|
||||||
|
|
||||||
function isSlowConnection () {
|
function isSlowConnection () {
|
||||||
if (import.meta.server) { return }
|
if (import.meta.server) { return }
|
||||||
|
|
||||||
|
@ -1,49 +1,6 @@
|
|||||||
import { useNuxtApp } from './nuxt'
|
|
||||||
|
|
||||||
export function toArray<T> (value: T | T[]): T[] {
|
export function toArray<T> (value: T | T[]): T[] {
|
||||||
return Array.isArray(value) ? value : [value]
|
return Array.isArray(value) ? value : [value]
|
||||||
}
|
}
|
||||||
|
|
||||||
type CallbackFn = () => void
|
export type CallbackFn = () => void
|
||||||
type ObserveFn = (element: Element, callback: CallbackFn) => () => void
|
export type ObserveFn = (element: Element, callback: CallbackFn) => () => void
|
||||||
|
|
||||||
export function useObserver (): { observe: ObserveFn } | undefined {
|
|
||||||
if (import.meta.server) { return }
|
|
||||||
|
|
||||||
const nuxtApp = useNuxtApp()
|
|
||||||
if (nuxtApp._observer) {
|
|
||||||
return nuxtApp._observer
|
|
||||||
}
|
|
||||||
|
|
||||||
let observer: IntersectionObserver | null = null
|
|
||||||
|
|
||||||
const callbacks = new Map<Element, CallbackFn>()
|
|
||||||
|
|
||||||
const observe: ObserveFn = (element, callback) => {
|
|
||||||
if (!observer) {
|
|
||||||
observer = new IntersectionObserver((entries) => {
|
|
||||||
for (const entry of entries) {
|
|
||||||
const callback = callbacks.get(entry.target)
|
|
||||||
const isVisible = entry.isIntersecting || entry.intersectionRatio > 0
|
|
||||||
if (isVisible && callback) { callback() }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
callbacks.set(element, callback)
|
|
||||||
observer.observe(element)
|
|
||||||
return () => {
|
|
||||||
callbacks.delete(element)
|
|
||||||
observer!.unobserve(element)
|
|
||||||
if (callbacks.size === 0) {
|
|
||||||
observer!.disconnect()
|
|
||||||
observer = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const _observer = nuxtApp._observer = {
|
|
||||||
observe,
|
|
||||||
}
|
|
||||||
|
|
||||||
return _observer
|
|
||||||
}
|
|
||||||
|
@ -1,9 +1,40 @@
|
|||||||
import { createStaticVNode, createVNode, defineComponent, getCurrentInstance, h, onBeforeUnmount, onMounted, ref } from 'vue'
|
import { createStaticVNode, createVNode, defineComponent, getCurrentInstance, h, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||||
import type { Component, Ref } from 'vue'
|
import type { Component, Ref } from 'vue'
|
||||||
// import ClientOnly from '#app/components/client-only'
|
// import ClientOnly from '#app/components/client-only'
|
||||||
import { useObserver } from '#app/utils'
|
import type { ObserveFn } from '#app/utils'
|
||||||
import { getFragmentHTML } from '#app/components/utils'
|
import { getFragmentHTML } from '#app/components/utils'
|
||||||
import { useNuxtApp } from '#app/nuxt'
|
import { useNuxtApp } from '#app/nuxt'
|
||||||
|
import { requestIdleCallback, cancelIdleCallback } from '#app/compat/idle-callback'
|
||||||
|
import { onNuxtReady } from '#app'
|
||||||
|
|
||||||
|
function useIntersectionObserver(options: IntersectionObserverInit) : {observe: ObserveFn} {
|
||||||
|
if (import.meta.server) { return {observe: () => () => {}}}
|
||||||
|
|
||||||
|
let observer: IntersectionObserver | null = null
|
||||||
|
|
||||||
|
const observe: ObserveFn = (element, callback) => {
|
||||||
|
if (!observer) {
|
||||||
|
observer = new IntersectionObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
const isVisible = entry.isIntersecting || entry.intersectionRatio > 0
|
||||||
|
if (isVisible && callback) { callback() }
|
||||||
|
}
|
||||||
|
}, options)
|
||||||
|
}
|
||||||
|
observer.observe(element)
|
||||||
|
return () => {
|
||||||
|
observer!.unobserve(element)
|
||||||
|
observer!.disconnect()
|
||||||
|
observer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const _observer = {
|
||||||
|
observe
|
||||||
|
}
|
||||||
|
|
||||||
|
return _observer
|
||||||
|
}
|
||||||
|
|
||||||
function elementIsVisibleInViewport (el: Element) {
|
function elementIsVisibleInViewport (el: Element) {
|
||||||
const { top, left, bottom, right } = el.getBoundingClientRect()
|
const { top, left, bottom, right } = el.getBoundingClientRect()
|
||||||
@ -35,7 +66,7 @@ export const createLazyIOClientPage = (componentLoader: Component) => {
|
|||||||
|
|
||||||
if (!isIntersecting.value) {
|
if (!isIntersecting.value) {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const observer = useObserver()
|
const observer = useIntersectionObserver(attrs.loader ?? {})
|
||||||
unobserve = observer!.observe(el.value as Element, () => {
|
unobserve = observer!.observe(el.value as Element, () => {
|
||||||
isIntersecting.value = true
|
isIntersecting.value = true
|
||||||
unobserve?.()
|
unobserve?.()
|
||||||
@ -69,10 +100,12 @@ export const createLazyNetworkClientPage = (componentLoader: Component) => {
|
|||||||
const isIdle = ref(false)
|
const isIdle = ref(false)
|
||||||
let idleHandle: number | null = null
|
let idleHandle: number | null = null
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
onNuxtReady(()=>{
|
||||||
idleHandle = requestIdleCallback(() => {
|
idleHandle = requestIdleCallback(() => {
|
||||||
isIdle.value = true
|
isIdle.value = true
|
||||||
cancelIdleCallback(idleHandle as unknown as number)
|
cancelIdleCallback(idleHandle as unknown as number)
|
||||||
idleHandle = null
|
idleHandle = null
|
||||||
|
}, attrs.loader ?? {timeout: 10000})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
Loading…
Reference in New Issue
Block a user