Skip to content

Commit 8332e97

Browse files
committed
目录自动滚动细节
1 parent ea4daca commit 8332e97

File tree

5 files changed

+69
-41
lines changed

5 files changed

+69
-41
lines changed

pages/[prefix]/[slug]/[...suffix].js

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import BLOG from '@/blog.config'
22
import { siteConfig } from '@/lib/config'
33
import { getGlobalData, getPost, getPostBlocks } from '@/lib/db/getSiteData'
4+
import { getPageTableOfContents } from '@/lib/notion/getPageTableOfContents'
45
import { uploadDataToAlgolia } from '@/lib/plugins/algolia'
56
import { checkSlugHasMorThanTwoSlash, getRecommendPost } from '@/lib/utils/post'
67
import { idToUuid } from 'notion-utils'
@@ -97,6 +98,15 @@ export async function getStaticProps({
9798
if (!props?.post?.blockMap) {
9899
props.post.blockMap = await getPostBlocks(props.post.id, from)
99100
}
101+
102+
// 目录默认加载
103+
if (props.post?.blockMap?.block) {
104+
props.post.content = Object.keys(props.post.blockMap.block).filter(
105+
key => props.post.blockMap.block[key]?.value?.parent_id === props.post.id
106+
)
107+
props.post.toc = getPageTableOfContents(props.post, props.post.blockMap)
108+
}
109+
100110
// 生成全文索引 && JSON.parse(BLOG.ALGOLIA_RECREATE_DATA)
101111
if (BLOG.ALGOLIA_APP_ID) {
102112
uploadDataToAlgolia(props?.post)

pages/[prefix]/[slug]/index.js

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import BLOG from '@/blog.config'
22
import { siteConfig } from '@/lib/config'
33
import { getGlobalData, getPost, getPostBlocks } from '@/lib/db/getSiteData'
4+
import { getPageTableOfContents } from '@/lib/notion/getPageTableOfContents'
45
import { uploadDataToAlgolia } from '@/lib/plugins/algolia'
56
import { checkSlugHasOneSlash, getRecommendPost } from '@/lib/utils/post'
67
import { idToUuid } from 'notion-utils'
@@ -86,6 +87,15 @@ export async function getStaticProps({ params: { prefix, slug }, locale }) {
8687
if (!props?.post?.blockMap) {
8788
props.post.blockMap = await getPostBlocks(props.post.id, from)
8889
}
90+
91+
// 目录默认加载
92+
if (props.post?.blockMap?.block) {
93+
props.post.content = Object.keys(props.post.blockMap.block).filter(
94+
key => props.post.blockMap.block[key]?.value?.parent_id === props.post.id
95+
)
96+
props.post.toc = getPageTableOfContents(props.post, props.post.blockMap)
97+
}
98+
8999
// 生成全文索引 && JSON.parse(BLOG.ALGOLIA_RECREATE_DATA)
90100
if (BLOG.ALGOLIA_APP_ID) {
91101
uploadDataToAlgolia(props?.post)

pages/[prefix]/index.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,6 @@ const Slug = props => {
5555
setLock(true)
5656
} else {
5757
setLock(false)
58-
if (!lock && post?.blockMap?.block) {
59-
post.content = Object.keys(post.blockMap.block).filter(
60-
key => post.blockMap.block[key]?.value?.parent_id === post.id
61-
)
62-
post.toc = getPageTableOfContents(post, post.blockMap)
63-
}
6458
}
6559

6660
// 读取上次记录 自动提交密码
@@ -171,6 +165,14 @@ export async function getStaticProps({ params: { prefix }, locale }) {
171165
props.post.blockMap = await getPostBlocks(props.post.id, from)
172166
}
173167

168+
// 目录默认加载
169+
if (props.post?.blockMap?.block) {
170+
props.post.content = Object.keys(props.post.blockMap.block).filter(
171+
key => props.post.blockMap.block[key]?.value?.parent_id === props.post.id
172+
)
173+
props.post.toc = getPageTableOfContents(props.post, props.post.blockMap)
174+
}
175+
174176
// 生成全文索引 && process.env.npm_lifecycle_event === 'build' && JSON.parse(BLOG.ALGOLIA_RECREATE_DATA)
175177
if (BLOG.ALGOLIA_APP_ID) {
176178
uploadDataToAlgolia(props?.post)

themes/magzine/components/Catalog.js

+36-34
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import throttle from 'lodash.throttle'
22
import { uuidToId } from 'notion-utils'
3-
import { useCallback, useEffect, useRef, useState } from 'react'
3+
import { useEffect, useRef, useState } from 'react'
44
import Progress from './Progress'
55

66
/**
@@ -9,7 +9,7 @@ import Progress from './Progress'
99
* @returns {JSX.Element}
1010
* @constructor
1111
*/
12-
const Catalog = ({ toc, className }) => {
12+
const Catalog = ({ post, toc, className }) => {
1313
const tocIds = []
1414

1515
// 目录自动滚动
@@ -19,43 +19,45 @@ const Catalog = ({ toc, className }) => {
1919

2020
// 监听滚动事件
2121
useEffect(() => {
22-
window.addEventListener('scroll', actionSectionScrollSpy)
23-
actionSectionScrollSpy()
22+
if (toc && toc.length > 1) {
23+
actionSectionScrollSpy()
24+
window.addEventListener('scroll', actionSectionScrollSpy)
25+
}
26+
setTimeout(() => {
27+
console.log('目录', post, toc)
28+
}, 1000)
2429
return () => {
2530
window.removeEventListener('scroll', actionSectionScrollSpy)
2631
}
2732
}, [])
2833

2934
const throttleMs = 200
30-
const actionSectionScrollSpy = useCallback(
31-
throttle(() => {
32-
const sections = document.getElementsByClassName('notion-h')
33-
let prevBBox = null
34-
let currentSectionId = activeSection
35-
for (let i = 0; i < sections.length; ++i) {
36-
const section = sections[i]
37-
if (!section || !(section instanceof Element)) continue
38-
if (!currentSectionId) {
39-
currentSectionId = section.getAttribute('data-id')
40-
}
41-
const bbox = section.getBoundingClientRect()
42-
const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0
43-
const offset = Math.max(150, prevHeight / 4)
44-
// GetBoundingClientRect returns values relative to viewport
45-
if (bbox.top - offset < 0) {
46-
currentSectionId = section.getAttribute('data-id')
47-
prevBBox = bbox
48-
continue
49-
}
50-
// No need to continue loop, if last element has been detected
51-
break
35+
const actionSectionScrollSpy = throttle(() => {
36+
const sections = document.getElementsByClassName('notion-h')
37+
let prevBBox = null
38+
let currentSectionId = activeSection
39+
for (let i = 0; i < sections.length; ++i) {
40+
const section = sections[i]
41+
if (!section || !(section instanceof Element)) continue
42+
if (!currentSectionId) {
43+
currentSectionId = section.getAttribute('data-id')
5244
}
53-
setActiveSection(currentSectionId)
54-
const index = tocIds.indexOf(currentSectionId) || 0
55-
tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' })
56-
console.log(tRef?.current)
57-
}, throttleMs)
58-
)
45+
const bbox = section.getBoundingClientRect()
46+
const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0
47+
const offset = Math.max(150, prevHeight / 4)
48+
// GetBoundingClientRect returns values relative to viewport
49+
if (bbox.top - offset < 0) {
50+
currentSectionId = section.getAttribute('data-id')
51+
prevBBox = bbox
52+
continue
53+
}
54+
// No need to continue loop, if last element has been detected
55+
break
56+
}
57+
setActiveSection(currentSectionId)
58+
const index = tocIds.indexOf(currentSectionId) || 0
59+
tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' })
60+
}, throttleMs)
5961

6062
// 无目录就直接返回空
6163
if (!toc || toc.length < 1) {
@@ -68,10 +70,10 @@ const Catalog = ({ toc, className }) => {
6870
<Progress />
6971
</div>
7072
<div
71-
className='overflow-y-auto scroll-hidden lg:max-h-dvh max-h-44'
73+
className='overflow-y-auto scroll-hidden lg:max-h-96 max-h-44'
7274
ref={tRef}>
7375
<nav className='h-full text-black'>
74-
{toc.map(tocItem => {
76+
{toc?.map(tocItem => {
7577
const id = uuidToId(tocItem.id)
7678
tocIds.push(id)
7779
return (

themes/magzine/index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,11 @@ const LayoutSlug = props => {
189189
{/* 文章区块分为三列 */}
190190
<div className='grid grid-cols-1 lg:grid-cols-5 gap-8 py-12'>
191191
<div className='h-full lg:col-span-1 hidden lg:block'>
192-
<Catalog toc={post?.toc} className='sticky top-20' />
192+
<Catalog
193+
post={post}
194+
toc={post?.toc || []}
195+
className='sticky top-20'
196+
/>
193197
</div>
194198

195199
{/* Notion文章主体 */}

0 commit comments

Comments
 (0)