mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
performance
This commit is contained in:
@@ -2,7 +2,7 @@ import BLOG from '@/blog.config'
|
||||
import BlogPostCard from './BlogPostCard'
|
||||
import BlogPostListEmpty from './BlogPostListEmpty'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import React from 'react'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import CONFIG from '../config'
|
||||
import { getListByPage } from '@/lib/utils'
|
||||
|
||||
@@ -15,7 +15,7 @@ import { getListByPage } from '@/lib/utils'
|
||||
*/
|
||||
const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG.POST_LIST_SUMMARY, siteInfo }) => {
|
||||
const postsPerPage = BLOG.POSTS_PER_PAGE
|
||||
const [page, updatePage] = React.useState(1)
|
||||
const [page, updatePage] = useState(1)
|
||||
const postsToShow = getListByPage(posts, page, postsPerPage)
|
||||
|
||||
let hasMore = false
|
||||
@@ -41,14 +41,14 @@ const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG.PO
|
||||
}
|
||||
|
||||
// 监听滚动
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
window.addEventListener('scroll', scrollTrigger)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', scrollTrigger)
|
||||
}
|
||||
})
|
||||
|
||||
const targetRef = React.useRef(null)
|
||||
const targetRef = useRef(null)
|
||||
const { locale } = useGlobal()
|
||||
|
||||
if (!postsToShow || postsToShow.length === 0) {
|
||||
|
||||
@@ -27,8 +27,8 @@ const Catalog = ({ toc }) => {
|
||||
// 同步选中目录事件
|
||||
const [activeSection, setActiveSection] = useState(null)
|
||||
|
||||
const throttleMs = 200
|
||||
const actionSectionScrollSpy = useCallback(throttle(() => {
|
||||
console.log('目录')
|
||||
const sections = document.getElementsByClassName('notion-h')
|
||||
let prevBBox = null
|
||||
let currentSectionId = activeSection
|
||||
@@ -53,7 +53,7 @@ const Catalog = ({ toc }) => {
|
||||
setActiveSection(currentSectionId)
|
||||
const index = tocIds.indexOf(currentSectionId) || 0
|
||||
tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' })
|
||||
}, throttleMs))
|
||||
}, 200))
|
||||
|
||||
// 无目录就直接返回空
|
||||
if (!toc || toc.length < 1) {
|
||||
|
||||
@@ -26,23 +26,11 @@ const NavBar = props => {
|
||||
slideOverRef?.current?.toggleSlideOvers()
|
||||
}
|
||||
|
||||
// 监听滚动
|
||||
useEffect(() => {
|
||||
scrollTrigger()
|
||||
window.addEventListener('scroll', scrollTrigger)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', scrollTrigger)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const throttleMs = 200
|
||||
|
||||
/**
|
||||
* 根据滚动条,切换导航栏样式
|
||||
*/
|
||||
const scrollTrigger = useCallback(throttle(() => {
|
||||
const scrollS = window.scrollY
|
||||
|
||||
// 导航栏设置 白色背景
|
||||
if (scrollS <= 0) {
|
||||
setFixedNav(false)
|
||||
@@ -60,7 +48,16 @@ const NavBar = props => {
|
||||
setTextWhite(false)
|
||||
setBgWhite(true)
|
||||
}
|
||||
}, throttleMs))
|
||||
}, 200))
|
||||
|
||||
// 监听滚动
|
||||
useEffect(() => {
|
||||
scrollTrigger()
|
||||
window.addEventListener('scroll', scrollTrigger)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', scrollTrigger)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// 监听导航栏显示文字
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 顶部页面阅读进度条
|
||||
* @returns {JSX.Element}
|
||||
* @constructor
|
||||
*/
|
||||
const Progress = ({ targetRef, showPercent = true }) => {
|
||||
const currentRef = targetRef?.current || targetRef
|
||||
const [percent, changePercent] = useState(0)
|
||||
const scrollListener = () => {
|
||||
const target = currentRef || (isBrowser() && document.getElementById('article-wrapper'))
|
||||
if (target) {
|
||||
const clientHeight = target.clientHeight
|
||||
const scrollY = window.pageYOffset
|
||||
const fullHeight = clientHeight - window.outerHeight
|
||||
let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0))
|
||||
if (per > 100) per = 100
|
||||
if (per < 0) per = 0
|
||||
changePercent(per)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('scroll', scrollListener)
|
||||
return () => document.removeEventListener('scroll', scrollListener)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="h-4 w-full shadow-2xl bg-gray-700 rounded-sm">
|
||||
<div
|
||||
className="h-4 bg-indigo-600 duration-200 rounded-sm"
|
||||
style={{ width: `${percent}%` }}
|
||||
>
|
||||
{showPercent && (
|
||||
<div className="text-right text-white text-xs">{percent}%</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Progress
|
||||
@@ -7,36 +7,50 @@ import { useEffect, useState } from 'react'
|
||||
*/
|
||||
export default function ReadingProgress() {
|
||||
const [scrollPercentage, setScrollPercentage] = useState(0)
|
||||
|
||||
function handleScroll() {
|
||||
const scrollHeight = document.documentElement.scrollHeight
|
||||
const clientHeight = document.documentElement.clientHeight
|
||||
const scrollY = window.scrollY || window.pageYOffset
|
||||
|
||||
const percent = Math.floor((scrollY / (scrollHeight - clientHeight)) * 100)
|
||||
setScrollPercentage(percent)
|
||||
}
|
||||
|
||||
// 监听滚动事件
|
||||
useEffect(() => {
|
||||
let requestId
|
||||
|
||||
function handleScroll() {
|
||||
const scrollHeight = document.documentElement.scrollHeight
|
||||
const clientHeight = document.documentElement.clientHeight
|
||||
const scrollY = window.scrollY || window.pageYOffset
|
||||
|
||||
const percent = Math.floor((scrollY / (scrollHeight - clientHeight)) * 100)
|
||||
setScrollPercentage(percent)
|
||||
|
||||
requestId = requestAnimationFrame(handleScroll)
|
||||
function updateScrollPercentage() {
|
||||
handleScroll()
|
||||
requestId = null
|
||||
}
|
||||
|
||||
handleScroll() // 初始化滚动位置
|
||||
function handleAnimationFrame() {
|
||||
if (requestId) {
|
||||
return
|
||||
}
|
||||
requestId = requestAnimationFrame(updateScrollPercentage)
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', handleAnimationFrame)
|
||||
return () => {
|
||||
cancelAnimationFrame(requestId)
|
||||
window.removeEventListener('scroll', handleAnimationFrame)
|
||||
if (requestId) {
|
||||
cancelAnimationFrame(requestId)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (<>
|
||||
<div title={'阅读进度'}
|
||||
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
|
||||
className={`${scrollPercentage > 0 ? 'w-10 h-10 ' : 'w-0 h-0 opacity-0'} group cursor-pointer hover:bg-black hover:bg-opacity-10 rounded-full flex justify-center items-center duration-200 transition-all`} >
|
||||
<ArrowSmallUp className={'w-5 h-5 hidden group-hover:block'} />
|
||||
<div className='group-hover:hidden text-xs flex justify-center items-center rounded-full w-6 h-6 bg-black text-white'>
|
||||
{scrollPercentage < 100 ? scrollPercentage : <ArrowSmallUp className={'w-5 h-5 fill-white'} />}
|
||||
</div>
|
||||
return (<div
|
||||
title={'阅读进度'}
|
||||
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
|
||||
className={`${scrollPercentage > 0 ? 'w-10 h-10 ' : 'w-0 h-0 opacity-0'} group cursor-pointer hover:bg-black hover:bg-opacity-10 rounded-full flex justify-center items-center duration-200 transition-all`}
|
||||
>
|
||||
<ArrowSmallUp className={'w-5 h-5 hidden group-hover:block'} />
|
||||
<div className='group-hover:hidden text-xs flex justify-center items-center rounded-full w-6 h-6 bg-black text-white'>
|
||||
{scrollPercentage < 100 ? scrollPercentage : <ArrowSmallUp className={'w-5 h-5 fill-white'} />}
|
||||
</div>
|
||||
|
||||
</>)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import throttle from 'lodash.throttle'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import FloatDarkModeButton from './FloatDarkModeButton'
|
||||
import JumpToTopButton from './JumpToTopButton'
|
||||
|
||||
/**
|
||||
* 悬浮在右下角的按钮,当页面向下滚动100px时会出现
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
export default function RightFloatArea({ floatSlot }) {
|
||||
const [showFloatButton, switchShow] = useState(false)
|
||||
const scrollListener = useCallback(throttle(() => {
|
||||
const targetRef = document.getElementById('wrapper')
|
||||
const clientHeight = targetRef?.clientHeight
|
||||
const scrollY = window.pageYOffset
|
||||
const fullHeight = clientHeight - window.outerHeight
|
||||
let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0))
|
||||
if (per > 100) per = 100
|
||||
const shouldShow = scrollY > 100 && per > 0
|
||||
|
||||
// 右下角显示悬浮按钮
|
||||
if (shouldShow !== showFloatButton) {
|
||||
switchShow(shouldShow)
|
||||
}
|
||||
}, 200))
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('scroll', scrollListener)
|
||||
return () => document.removeEventListener('scroll', scrollListener)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className={(showFloatButton ? 'opacity-100 ' : 'invisible opacity-0') + ' duration-300 transition-all bottom-12 right-1 fixed justify-end z-20 text-white bg-indigo-500 dark:bg-hexo-black-gray rounded-sm'}>
|
||||
<div className={'justify-center flex flex-col items-center cursor-pointer'}>
|
||||
<FloatDarkModeButton />
|
||||
{floatSlot}
|
||||
<JumpToTopButton />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user