From 8d9eeb03037bd7a135700ae8523a72615aa77458 Mon Sep 17 00:00:00 2001 From: EmberSparks Date: Mon, 2 Mar 2026 19:38:39 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E5=88=86=E6=89=B9=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E4=BB=93=E5=BA=93=E5=88=97=E8=A1=A8=E5=87=8F=E5=B0=91=E6=8E=92?= =?UTF-8?q?=E5=BA=8F=E5=8D=A1=E9=A1=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/view.ts | 55 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/src/view.ts b/src/view.ts index 851bf26..a87b7af 100644 --- a/src/view.ts +++ b/src/view.ts @@ -80,6 +80,7 @@ export class GithubStarsView extends ItemView { virtualItemsEl: HTMLElement | null = null; virtualBottomSpacerEl: HTMLElement | null = null; virtualMeasureFrameId: number | null = null; + repoRenderVersion: number = 0; constructor(leaf: WorkspaceLeaf, plugin: GithubStarsPlugin) { super(leaf); @@ -394,6 +395,26 @@ export class GithubStarsView extends ItemView { this.renderVirtualizedWindow(); }; + /** + * 等待下一帧,避免一次性大批量 DOM 插入导致主线程长时间阻塞 + */ + private waitForNextFrame(): Promise { + return new Promise((resolve) => { + window.requestAnimationFrame(() => resolve()); + }); + } + + /** + * 根据仓库数量动态选择分批渲染尺寸 + */ + private getRepoRenderBatchSize(totalCount: number): number { + if (totalCount > 1400) return 10; + if (totalCount > 900) return 14; + if (totalCount > 500) return 20; + if (totalCount > 220) return 28; + return 36; + } + /** * 开始编辑标签 */ @@ -958,6 +979,8 @@ export class GithubStarsView extends ItemView { console.warn('repoContainer not initialized'); return; } + const renderVersion = ++this.repoRenderVersion; + if (!this.githubRepositories || this.githubRepositories.length === 0) { this.disableRepoVirtualization(); this.repoContainer.empty(); @@ -979,11 +1002,11 @@ export class GithubStarsView extends ItemView { this.updateTotalStarsCount(sortedRepos.length); if (sortedRepos.length < REPO_VIRTUALIZATION_THRESHOLD) { - this.renderFullRepositories(sortedRepos); + void this.renderFullRepositories(sortedRepos, renderVersion); return; } - this.renderVirtualizedRepositories(sortedRepos); + this.renderVirtualizedRepositories(sortedRepos, renderVersion); } /** @@ -1071,20 +1094,37 @@ export class GithubStarsView extends ItemView { /** * 常规渲染(非虚拟化) */ - private renderFullRepositories(repositories: RenderRepository[]): void { + private async renderFullRepositories(repositories: RenderRepository[], renderVersion: number): Promise { if (!this.repoContainer) return; this.disableRepoVirtualization(); this.repoContainer.empty(); - repositories.forEach((repo) => { - this.renderRepositoryCard(repo, this.repoContainer); - }); + const batchSize = this.getRepoRenderBatchSize(repositories.length); + + for (let start = 0; start < repositories.length; start += batchSize) { + if (renderVersion !== this.repoRenderVersion || !this.repoContainer) { + return; + } + + const end = Math.min(repositories.length, start + batchSize); + for (let index = start; index < end; index++) { + if (renderVersion !== this.repoRenderVersion || !this.repoContainer) { + return; + } + this.renderRepositoryCard(repositories[index], this.repoContainer); + } + + if (end < repositories.length) { + await this.waitForNextFrame(); + } + } } /** * 虚拟列表渲染(仅渲染可视区域) */ - private renderVirtualizedRepositories(repositories: RenderRepository[]): void { + private renderVirtualizedRepositories(repositories: RenderRepository[], renderVersion: number): void { if (!this.repoContainer) return; + if (renderVersion !== this.repoRenderVersion) return; this.virtualizedRepos = repositories; if (!this.isRepoListVirtualized || !this.virtualItemsEl || !this.virtualTopSpacerEl || !this.virtualBottomSpacerEl) { @@ -2010,6 +2050,7 @@ export class GithubStarsView extends ItemView { } onClose(): Promise { + this.repoRenderVersion += 1; if (this.repoContainer) { this.repoContainer.removeEventListener('scroll', this.handleRepoContainerScroll); }