Splitting things up
A View should contain only:
onOpen()
onClose()
render()
bindEvents()The overall process Read the structure, build a mental map
Keywords: if/switch, render/refresh/update, onclick/addEventListener
Label things in your head
Distinguish: state, pure logic (compute/decide), side effects (DOM/events), performance/debounce/scroll
Extract functions, name them, and call them
When to extract a function
- more than 8 lines
- you can describe what it does in one sentence
- it’s an eyesore sitting inline
Split into files
When some functions do similar things, are often used together, and have similar names
- create a new file, e.g. save.ts
- cut them over untouched
- export/import
Layer it
view-render-logic-store-flux-MVC-MVVM
Stop when it’s good enough
Once you can tell at a glance what each line does, you’re done
Splitting out the CSS
Create a matching css.ts Note: change the class names and ids
/**
* 样式加载器 - 负责注入和管理 CSS
*/
export class reviewStyle {
private static styleId = 'learning-overview-styles';
private static isInjected = false;
/**
* 注入样式到页面
*/
static inject(): void {
if (this.isInjected || document.getElementById(this.styleId)) {
return;
}
const styleEl = document.createElement('style');
styleEl.id = this.styleId;
styleEl.textContent = this.getStyles();
document.head.appendChild(styleEl);
this.isInjected = true;
}
/**
* 移除样式
*/
static remove(): void {
const styleEl = document.getElementById(this.styleId);
if (styleEl) {
styleEl.remove();
this.isInjected = false;
}
}
/**
* 获取所有样式(从这里统一管理)
*/
private static getStyles(): string {
return `
// 插入对应的样式
`
;
}
}Import the file at the top
import { reviewStyle } from '../style/reviewStyle';Inject it in async onOpen()
reviewStyle.inject();Splitting out a service component Create the matching component file
export class sideOverviewService {
constructor(
private plugin: LearningSystemPlugin,
private state: ViewState
) {}
// 把 jumpToSource、saveAnnotation、quickGenerateFlashcard 等
// 业务逻辑方法移到这里
async jumpToSource(unit: ContentUnit, app: App): Promise<void> { }
async saveAnnotation(unitId: string, content: string): Promise<void> { }
async quickGenerateFlashcard(unit: ContentUnit): Promise<void> { }
// ...
} Import
import { sideOverviewService } from '../service/sideOverviewService';Use
export class SidebarOverviewView extends ItemView {
plugin: LearningSystemPlugin;
// 使用状态管理器
private state: ViewState;
// 使用service组件
private overviewService: sideOverviewService;
private _forceMainMode: boolean;
constructor(leaf: WorkspaceLeaf, plugin: LearningSystemPlugin, forceMainMode = false) {
super(leaf);
this.plugin = plugin;
this._forceMainMode = forceMainMode;
// 初始化状态
this.state = new ViewState(forceMainMode);
// 初始化组件
this.initializeComponents();private initializeComponents(): void {
// 初始化 service
this.overviewService = new OverviewService(this.plugin, this.state);
// 工具栏回调
this.toolbar = new Toolbar(this.state, {
// ...
});
// ...
}