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, {
    // ...
  });
  // ...
}