1
- import dynamic from 'next/dynamic'
2
1
import Tabs from '@/components/Tabs'
2
+ import { siteConfig } from '@/lib/config'
3
3
import { isBrowser , isSearchEngineBot } from '@/lib/utils'
4
+ import dynamic from 'next/dynamic'
4
5
import { useRouter } from 'next/router'
6
+ import { useEffect , useRef , useState } from 'react'
5
7
import Artalk from './Artalk'
6
- import { siteConfig } from '@/lib/config'
7
8
8
9
const WalineComponent = dynamic (
9
10
( ) => {
@@ -57,11 +58,14 @@ const ValineComponent = dynamic(() => import('@/components/ValineComponent'), {
57
58
58
59
/**
59
60
* 评论组件
61
+ * 只有当前组件在浏览器可见范围内才会加载内容
60
62
* @param {* } param0
61
63
* @returns
62
64
*/
63
- const Comment = ( { siteInfo , frontMatter, className } ) => {
65
+ const Comment = ( { frontMatter, className } ) => {
64
66
const router = useRouter ( )
67
+ const [ shouldLoad , setShouldLoad ] = useState ( false )
68
+ const commentRef = useRef ( null )
65
69
66
70
const COMMENT_ARTALK_SERVER = siteConfig ( 'COMMENT_ARTALK_SERVER' )
67
71
const COMMENT_TWIKOO_ENV_ID = siteConfig ( 'COMMENT_TWIKOO_ENV_ID' )
@@ -73,65 +77,125 @@ const Comment = ({ siteInfo, frontMatter, className }) => {
73
77
const COMMENT_GITALK_CLIENT_ID = siteConfig ( 'COMMENT_GITALK_CLIENT_ID' )
74
78
const COMMENT_WEBMENTION_ENABLE = siteConfig ( 'COMMENT_WEBMENTION_ENABLE' )
75
79
76
- if ( isSearchEngineBot ( ) ) {
77
- return null
78
- }
80
+ useEffect ( ( ) => {
81
+ // Check if the component is visible in the viewport
82
+ const observer = new IntersectionObserver ( entries => {
83
+ entries . forEach ( entry => {
84
+ if ( entry . isIntersecting ) {
85
+ setShouldLoad ( true )
86
+ observer . unobserve ( entry . target )
87
+ }
88
+ } )
89
+ } )
90
+
91
+ if ( commentRef . current ) {
92
+ observer . observe ( commentRef . current )
93
+ }
94
+
95
+ return ( ) => {
96
+ if ( commentRef . current ) {
97
+ observer . unobserve ( commentRef . current )
98
+ }
99
+ }
100
+ } , [ frontMatter ] )
79
101
80
102
// 当连接中有特殊参数时跳转到评论区
81
- if ( isBrowser && ( 'giscus' in router . query || router . query . target === 'comment' ) ) {
103
+ if (
104
+ isBrowser &&
105
+ ( 'giscus' in router . query || router . query . target === 'comment' )
106
+ ) {
82
107
setTimeout ( ( ) => {
83
108
const url = router . asPath . replace ( '?target=comment' , '' )
84
109
history . replaceState ( { } , '' , url )
85
- document ?. getElementById ( 'comment' ) ?. scrollIntoView ( { block : 'start' , behavior : 'smooth' } )
110
+ document
111
+ ?. getElementById ( 'comment' )
112
+ ?. scrollIntoView ( { block : 'start' , behavior : 'smooth' } )
86
113
} , 1000 )
87
114
}
88
115
89
116
if ( ! frontMatter ) {
90
117
return < > Loading...</ >
91
118
}
92
119
120
+ if ( isSearchEngineBot ( ) ) {
121
+ return null
122
+ }
123
+
93
124
return (
94
- < div key = { frontMatter ?. id } id = 'comment' className = { `comment mt-5 text-gray-800 dark:text-gray-300 ${ className || '' } ` } >
95
- < Tabs >
96
- { COMMENT_ARTALK_SERVER && ( < div key = 'Artalk' >
97
- < Artalk />
98
- </ div > ) }
99
-
100
- { COMMENT_TWIKOO_ENV_ID && ( < div key = 'Twikoo' >
101
- < TwikooCompenent />
102
- </ div > ) }
103
-
104
- { COMMENT_WALINE_SERVER_URL && ( < div key = 'Waline' >
105
- < WalineComponent />
106
- </ div > ) }
107
-
108
- { COMMENT_VALINE_APP_ID && ( < div key = 'Valine' name = 'reply' >
109
- < ValineComponent path = { frontMatter . id } />
110
- </ div > ) }
111
-
112
- { COMMENT_GISCUS_REPO && (
113
- < div key = "Giscus" >
114
- < GiscusComponent className = "px-2" />
115
- </ div >
116
- ) }
117
-
118
- { COMMENT_CUSDIS_APP_ID && ( < div key = 'Cusdis' >
119
- < CusdisComponent frontMatter = { frontMatter } />
120
- </ div > ) }
121
-
122
- { COMMENT_UTTERRANCES_REPO && ( < div key = 'Utterance' >
123
- < UtterancesComponent issueTerm = { frontMatter . id } className = 'px-2' />
124
- </ div > ) }
125
-
126
- { COMMENT_GITALK_CLIENT_ID && ( < div key = 'GitTalk' >
127
- < GitalkComponent frontMatter = { frontMatter } />
128
- </ div > ) }
129
-
130
- { COMMENT_WEBMENTION_ENABLE && ( < div key = 'WebMention' >
131
- < WebMentionComponent frontMatter = { frontMatter } className = "px-2" />
132
- </ div > ) }
133
- </ Tabs >
125
+ < div
126
+ key = { frontMatter ?. id }
127
+ id = 'comment'
128
+ ref = { commentRef }
129
+ className = { `comment mt-5 text-gray-800 dark:text-gray-300 ${ className || '' } ` } >
130
+ { /* 延迟加载评论区 */ }
131
+ { ! shouldLoad && (
132
+ < div className = 'text-center' >
133
+ Loading...
134
+ < i className = 'fas fa-spinner animate-spin text-3xl ' />
134
135
</ div >
136
+ ) }
137
+
138
+ { shouldLoad && (
139
+ < Tabs >
140
+ { COMMENT_ARTALK_SERVER && (
141
+ < div key = 'Artalk' >
142
+ < Artalk />
143
+ </ div >
144
+ ) }
145
+
146
+ { COMMENT_TWIKOO_ENV_ID && (
147
+ < div key = 'Twikoo' >
148
+ < TwikooCompenent />
149
+ </ div >
150
+ ) }
151
+
152
+ { COMMENT_WALINE_SERVER_URL && (
153
+ < div key = 'Waline' >
154
+ < WalineComponent />
155
+ </ div >
156
+ ) }
157
+
158
+ { COMMENT_VALINE_APP_ID && (
159
+ < div key = 'Valine' name = 'reply' >
160
+ < ValineComponent path = { frontMatter . id } />
161
+ </ div >
162
+ ) }
163
+
164
+ { COMMENT_GISCUS_REPO && (
165
+ < div key = 'Giscus' >
166
+ < GiscusComponent className = 'px-2' />
167
+ </ div >
168
+ ) }
169
+
170
+ { COMMENT_CUSDIS_APP_ID && (
171
+ < div key = 'Cusdis' >
172
+ < CusdisComponent frontMatter = { frontMatter } />
173
+ </ div >
174
+ ) }
175
+
176
+ { COMMENT_UTTERRANCES_REPO && (
177
+ < div key = 'Utterance' >
178
+ < UtterancesComponent
179
+ issueTerm = { frontMatter . id }
180
+ className = 'px-2'
181
+ />
182
+ </ div >
183
+ ) }
184
+
185
+ { COMMENT_GITALK_CLIENT_ID && (
186
+ < div key = 'GitTalk' >
187
+ < GitalkComponent frontMatter = { frontMatter } />
188
+ </ div >
189
+ ) }
190
+
191
+ { COMMENT_WEBMENTION_ENABLE && (
192
+ < div key = 'WebMention' >
193
+ < WebMentionComponent frontMatter = { frontMatter } className = 'px-2' />
194
+ </ div >
195
+ ) }
196
+ </ Tabs >
197
+ ) }
198
+ </ div >
135
199
)
136
200
}
137
201
0 commit comments