Skip to content

Element Plus 企业级应用架构设计

学习目标

今天我们将学习如何设计基于 Element Plus 的企业级应用架构,掌握大型应用的架构设计原则、微前端实践、状态管理和性能优化策略。

  • 理解企业级应用架构设计原则
  • 掌握微前端架构的设计和实现
  • 学习大型应用的状态管理策略
  • 了解性能优化和安全性考虑
  • 实现可扩展的应用架构

1. 企业级应用架构设计原则

1.1 架构设计原则

typescript
// packages/architecture/src/core/architecture-principles.ts

/**
 * 企业级应用架构设计原则
 */
export interface ArchitecturePrinciples {
  // 单一职责原则
  singleResponsibility: boolean
  // 开放封闭原则
  openClosed: boolean
  // 依赖倒置原则
  dependencyInversion: boolean
  // 接口隔离原则
  interfaceSegregation: boolean
  // 最少知识原则
  leastKnowledge: boolean
}

/**
 * 架构层次结构
 */
export enum ArchitectureLayer {
  PRESENTATION = 'presentation',     // 表现层
  APPLICATION = 'application',       // 应用层
  DOMAIN = 'domain',                // 领域层
  INFRASTRUCTURE = 'infrastructure'  // 基础设施层
}

/**
 * 架构模式
 */
export enum ArchitecturePattern {
  MVC = 'mvc',                      // Model-View-Controller
  MVP = 'mvp',                      // Model-View-Presenter
  MVVM = 'mvvm',                    // Model-View-ViewModel
  CLEAN = 'clean',                  // Clean Architecture
  HEXAGONAL = 'hexagonal',          // Hexagonal Architecture
  ONION = 'onion'                   // Onion Architecture
}

/**
 * 架构配置
 */
export interface ArchitectureConfig {
  pattern: ArchitecturePattern
  layers: ArchitectureLayer[]
  principles: ArchitecturePrinciples
  scalability: {
    horizontal: boolean
    vertical: boolean
    microservices: boolean
    microfrontends: boolean
  }
  performance: {
    caching: boolean
    lazyLoading: boolean
    codesplitting: boolean
    bundleOptimization: boolean
  }
  security: {
    authentication: boolean
    authorization: boolean
    dataEncryption: boolean
    inputValidation: boolean
  }
  monitoring: {
    logging: boolean
    metrics: boolean
    tracing: boolean
    alerting: boolean
  }
}

/**
 * 架构管理器
 */
export class ArchitectureManager {
  private config: ArchitectureConfig
  private modules = new Map<string, ArchitectureModule>()
  private dependencies = new Map<string, string[]>()

  constructor(config: ArchitectureConfig) {
    this.config = config
  }

  /**
   * 注册架构模块
   */
  registerModule(module: ArchitectureModule): void {
    this.modules.set(module.name, module)
    this.dependencies.set(module.name, module.dependencies || [])
  }

  /**
   * 初始化架构
   */
  async initialize(): Promise<void> {
    // 验证架构配置
    this.validateConfiguration()
    
    // 解析模块依赖
    const sortedModules = this.resolveDependencies()
    
    // 按依赖顺序初始化模块
    for (const moduleName of sortedModules) {
      const module = this.modules.get(moduleName)!
      await module.initialize(this.config)
    }
  }

  /**
   * 验证架构配置
   */
  private validateConfiguration(): void {
    if (!this.config.pattern) {
      throw new Error('Architecture pattern is required')
    }
    
    if (!this.config.layers || this.config.layers.length === 0) {
      throw new Error('Architecture layers are required')
    }
    
    // 验证层次依赖关系
    this.validateLayerDependencies()
  }

  /**
   * 验证层次依赖关系
   */
  private validateLayerDependencies(): void {
    const layerOrder = [
      ArchitectureLayer.PRESENTATION,
      ArchitectureLayer.APPLICATION,
      ArchitectureLayer.DOMAIN,
      ArchitectureLayer.INFRASTRUCTURE
    ]
    
    // 确保层次顺序正确
    const configLayers = this.config.layers
    for (let i = 0; i < configLayers.length - 1; i++) {
      const currentIndex = layerOrder.indexOf(configLayers[i])
      const nextIndex = layerOrder.indexOf(configLayers[i + 1])
      
      if (currentIndex >= nextIndex) {
        throw new Error(`Invalid layer dependency: ${configLayers[i]} -> ${configLayers[i + 1]}`)
      }
    }
  }

  /**
   * 解析模块依赖
   */
  private resolveDependencies(): string[] {
    const visited = new Set<string>()
    const visiting = new Set<string>()
    const result: string[] = []

    const visit = (moduleName: string) => {
      if (visiting.has(moduleName)) {
        throw new Error(`Circular dependency detected: ${moduleName}`)
      }
      
      if (visited.has(moduleName)) {
        return
      }

      visiting.add(moduleName)
      
      const dependencies = this.dependencies.get(moduleName) || []
      for (const dependency of dependencies) {
        visit(dependency)
      }
      
      visiting.delete(moduleName)
      visited.add(moduleName)
      result.push(moduleName)
    }

    for (const moduleName of this.modules.keys()) {
      visit(moduleName)
    }

    return result
  }
}

/**
 * 架构模块接口
 */
export interface ArchitectureModule {
  name: string
  layer: ArchitectureLayer
  dependencies?: string[]
  initialize(config: ArchitectureConfig): Promise<void>
  destroy?(): Promise<void>
}

1.2 领域驱动设计 (DDD)

typescript
// packages/architecture/src/domain/domain-model.ts

/**
 * 实体基类
 */
export abstract class Entity<T> {
  protected readonly _id: T
  protected _createdAt: Date
  protected _updatedAt: Date

  constructor(id: T) {
    this._id = id
    this._createdAt = new Date()
    this._updatedAt = new Date()
  }

  get id(): T {
    return this._id
  }

  get createdAt(): Date {
    return this._createdAt
  }

  get updatedAt(): Date {
    return this._updatedAt
  }

  protected touch(): void {
    this._updatedAt = new Date()
  }

  equals(other: Entity<T>): boolean {
    return this._id === other._id
  }
}

/**
 * 值对象基类
 */
export abstract class ValueObject {
  abstract equals(other: ValueObject): boolean
  
  protected static isEqual(a: any, b: any): boolean {
    if (a === b) return true
    if (a == null || b == null) return false
    if (typeof a !== typeof b) return false
    
    if (typeof a === 'object') {
      const keysA = Object.keys(a)
      const keysB = Object.keys(b)
      
      if (keysA.length !== keysB.length) return false
      
      return keysA.every(key => this.isEqual(a[key], b[key]))
    }
    
    return false
  }
}

/**
 * 聚合根基类
 */
export abstract class AggregateRoot<T> extends Entity<T> {
  private _domainEvents: DomainEvent[] = []

  get domainEvents(): DomainEvent[] {
    return [...this._domainEvents]
  }

  protected addDomainEvent(event: DomainEvent): void {
    this._domainEvents.push(event)
  }

  clearDomainEvents(): void {
    this._domainEvents = []
  }
}

/**
 * 领域事件接口
 */
export interface DomainEvent {
  aggregateId: string
  eventType: string
  occurredOn: Date
  eventData: any
}

/**
 * 领域事件基类
 */
export abstract class BaseDomainEvent implements DomainEvent {
  public readonly aggregateId: string
  public readonly eventType: string
  public readonly occurredOn: Date
  public readonly eventData: any

  constructor(aggregateId: string, eventType: string, eventData: any) {
    this.aggregateId = aggregateId
    this.eventType = eventType
    this.eventData = eventData
    this.occurredOn = new Date()
  }
}

/**
 * 仓储接口
 */
export interface Repository<T extends AggregateRoot<any>> {
  findById(id: string): Promise<T | null>
  save(aggregate: T): Promise<void>
  delete(id: string): Promise<void>
}

/**
 * 领域服务接口
 */
export interface DomainService {
  name: string
}

/**
 * 应用服务接口
 */
export interface ApplicationService {
  name: string
}

// 示例:用户领域模型
export class UserId extends ValueObject {
  constructor(private readonly value: string) {
    super()
    if (!value || value.trim().length === 0) {
      throw new Error('UserId cannot be empty')
    }
  }

  getValue(): string {
    return this.value
  }

  equals(other: ValueObject): boolean {
    return other instanceof UserId && this.value === other.value
  }
}

export class UserEmail extends ValueObject {
  constructor(private readonly value: string) {
    super()
    if (!this.isValidEmail(value)) {
      throw new Error('Invalid email format')
    }
  }

  getValue(): string {
    return this.value
  }

  equals(other: ValueObject): boolean {
    return other instanceof UserEmail && this.value === other.value
  }

  private isValidEmail(email: string): boolean {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    return emailRegex.test(email)
  }
}

export class User extends AggregateRoot<UserId> {
  private _email: UserEmail
  private _name: string
  private _isActive: boolean

  constructor(id: UserId, email: UserEmail, name: string) {
    super(id.getValue())
    this._email = email
    this._name = name
    this._isActive = true
    
    this.addDomainEvent(new UserCreatedEvent(id.getValue(), {
      email: email.getValue(),
      name
    }))
  }

  get email(): UserEmail {
    return this._email
  }

  get name(): string {
    return this._name
  }

  get isActive(): boolean {
    return this._isActive
  }

  changeEmail(newEmail: UserEmail): void {
    if (!this._email.equals(newEmail)) {
      const oldEmail = this._email.getValue()
      this._email = newEmail
      this.touch()
      
      this.addDomainEvent(new UserEmailChangedEvent(this._id, {
        oldEmail,
        newEmail: newEmail.getValue()
      }))
    }
  }

  changeName(newName: string): void {
    if (this._name !== newName) {
      const oldName = this._name
      this._name = newName
      this.touch()
      
      this.addDomainEvent(new UserNameChangedEvent(this._id, {
        oldName,
        newName
      }))
    }
  }

  deactivate(): void {
    if (this._isActive) {
      this._isActive = false
      this.touch()
      
      this.addDomainEvent(new UserDeactivatedEvent(this._id, {}))
    }
  }

  activate(): void {
    if (!this._isActive) {
      this._isActive = true
      this.touch()
      
      this.addDomainEvent(new UserActivatedEvent(this._id, {}))
    }
  }
}

// 领域事件
export class UserCreatedEvent extends BaseDomainEvent {
  constructor(aggregateId: string, eventData: any) {
    super(aggregateId, 'UserCreated', eventData)
  }
}

export class UserEmailChangedEvent extends BaseDomainEvent {
  constructor(aggregateId: string, eventData: any) {
    super(aggregateId, 'UserEmailChanged', eventData)
  }
}

export class UserNameChangedEvent extends BaseDomainEvent {
  constructor(aggregateId: string, eventData: any) {
    super(aggregateId, 'UserNameChanged', eventData)
  }
}

export class UserDeactivatedEvent extends BaseDomainEvent {
  constructor(aggregateId: string, eventData: any) {
    super(aggregateId, 'UserDeactivated', eventData)
  }
}

export class UserActivatedEvent extends BaseDomainEvent {
  constructor(aggregateId: string, eventData: any) {
    super(aggregateId, 'UserActivated', eventData)
  }
}

// 用户仓储接口
export interface UserRepository extends Repository<User> {
  findByEmail(email: UserEmail): Promise<User | null>
  findActiveUsers(): Promise<User[]>
}

2. 微前端架构设计

2.1 微前端架构实现

typescript
// packages/microfrontend/src/core/microfrontend-manager.ts

export interface MicrofrontendConfig {
  name: string
  entry: string
  container: string
  activeRule: string | ((location: Location) => boolean)
  props?: Record<string, any>
  loader?: () => Promise<any>
  errorBoundary?: boolean
  sandbox?: boolean
  prefetch?: boolean
  preload?: boolean
}

export interface MicrofrontendLifecycle {
  bootstrap?: () => Promise<void>
  mount?: (props: any) => Promise<void>
  unmount?: (props: any) => Promise<void>
  update?: (props: any) => Promise<void>
}

export interface MicrofrontendApp extends MicrofrontendLifecycle {
  name: string
  status: 'NOT_LOADED' | 'LOADING' | 'LOADED' | 'MOUNTING' | 'MOUNTED' | 'UNMOUNTING' | 'ERROR'
  config: MicrofrontendConfig
  module?: any
}

export class MicrofrontendManager {
  private apps = new Map<string, MicrofrontendApp>()
  private currentApp: string | null = null
  private eventBus = new EventTarget()

  /**
   * 注册微前端应用
   */
  registerApp(config: MicrofrontendConfig): void {
    if (this.apps.has(config.name)) {
      throw new Error(`Microfrontend app ${config.name} already registered`)
    }

    const app: MicrofrontendApp = {
      name: config.name,
      status: 'NOT_LOADED',
      config,
      bootstrap: undefined,
      mount: undefined,
      unmount: undefined,
      update: undefined
    }

    this.apps.set(config.name, app)
    
    // 预加载
    if (config.preload) {
      this.preloadApp(config.name)
    }
  }

  /**
   * 启动微前端系统
   */
  async start(): Promise<void> {
    // 监听路由变化
    window.addEventListener('popstate', this.handleRouteChange.bind(this))
    window.addEventListener('pushstate', this.handleRouteChange.bind(this))
    window.addEventListener('replacestate', this.handleRouteChange.bind(this))
    
    // 初始路由检查
    await this.handleRouteChange()
  }

  /**
   * 处理路由变化
   */
  private async handleRouteChange(): Promise<void> {
    const activeApp = this.getActiveApp()
    
    if (activeApp && activeApp !== this.currentApp) {
      // 卸载当前应用
      if (this.currentApp) {
        await this.unmountApp(this.currentApp)
      }
      
      // 挂载新应用
      await this.mountApp(activeApp)
      this.currentApp = activeApp
    } else if (!activeApp && this.currentApp) {
      // 卸载当前应用
      await this.unmountApp(this.currentApp)
      this.currentApp = null
    }
  }

  /**
   * 获取当前激活的应用
   */
  private getActiveApp(): string | null {
    for (const [name, app] of this.apps) {
      if (this.isAppActive(app.config)) {
        return name
      }
    }
    return null
  }

  /**
   * 检查应用是否激活
   */
  private isAppActive(config: MicrofrontendConfig): boolean {
    if (typeof config.activeRule === 'function') {
      return config.activeRule(window.location)
    }
    
    if (typeof config.activeRule === 'string') {
      return window.location.pathname.startsWith(config.activeRule)
    }
    
    return false
  }

  /**
   * 预加载应用
   */
  private async preloadApp(name: string): Promise<void> {
    const app = this.apps.get(name)
    if (!app || app.status !== 'NOT_LOADED') {
      return
    }

    try {
      app.status = 'LOADING'
      await this.loadApp(app)
      app.status = 'LOADED'
    } catch (error) {
      app.status = 'ERROR'
      console.error(`Failed to preload app ${name}:`, error)
    }
  }

  /**
   * 加载应用
   */
  private async loadApp(app: MicrofrontendApp): Promise<void> {
    if (app.config.loader) {
      app.module = await app.config.loader()
    } else {
      // 动态导入
      app.module = await import(app.config.entry)
    }

    // 提取生命周期函数
    if (app.module.bootstrap) {
      app.bootstrap = app.module.bootstrap
    }
    if (app.module.mount) {
      app.mount = app.module.mount
    }
    if (app.module.unmount) {
      app.unmount = app.module.unmount
    }
    if (app.module.update) {
      app.update = app.module.update
    }
  }

  /**
   * 挂载应用
   */
  private async mountApp(name: string): Promise<void> {
    const app = this.apps.get(name)
    if (!app) {
      throw new Error(`App ${name} not found`)
    }

    try {
      // 加载应用
      if (app.status === 'NOT_LOADED') {
        app.status = 'LOADING'
        await this.loadApp(app)
        app.status = 'LOADED'
      }

      // 启动应用
      if (app.bootstrap && app.status === 'LOADED') {
        await app.bootstrap()
      }

      // 挂载应用
      app.status = 'MOUNTING'
      if (app.mount) {
        const props = {
          container: app.config.container,
          ...app.config.props,
          eventBus: this.eventBus
        }
        await app.mount(props)
      }
      app.status = 'MOUNTED'

      this.dispatchEvent('app:mounted', { name })
    } catch (error) {
      app.status = 'ERROR'
      console.error(`Failed to mount app ${name}:`, error)
      this.dispatchEvent('app:error', { name, error })
    }
  }

  /**
   * 卸载应用
   */
  private async unmountApp(name: string): Promise<void> {
    const app = this.apps.get(name)
    if (!app || app.status !== 'MOUNTED') {
      return
    }

    try {
      app.status = 'UNMOUNTING'
      if (app.unmount) {
        const props = {
          container: app.config.container,
          ...app.config.props
        }
        await app.unmount(props)
      }
      app.status = 'LOADED'

      this.dispatchEvent('app:unmounted', { name })
    } catch (error) {
      app.status = 'ERROR'
      console.error(`Failed to unmount app ${name}:`, error)
      this.dispatchEvent('app:error', { name, error })
    }
  }

  /**
   * 更新应用属性
   */
  async updateApp(name: string, props: Record<string, any>): Promise<void> {
    const app = this.apps.get(name)
    if (!app || app.status !== 'MOUNTED') {
      return
    }

    try {
      if (app.update) {
        await app.update(props)
      }
      this.dispatchEvent('app:updated', { name, props })
    } catch (error) {
      console.error(`Failed to update app ${name}:`, error)
      this.dispatchEvent('app:error', { name, error })
    }
  }

  /**
   * 获取应用状态
   */
  getAppStatus(name: string): string | null {
    const app = this.apps.get(name)
    return app ? app.status : null
  }

  /**
   * 获取所有应用
   */
  getApps(): MicrofrontendApp[] {
    return Array.from(this.apps.values())
  }

  /**
   * 发送事件
   */
  private dispatchEvent(type: string, detail: any): void {
    this.eventBus.dispatchEvent(new CustomEvent(type, { detail }))
  }

  /**
   * 监听事件
   */
  addEventListener(type: string, listener: EventListener): void {
    this.eventBus.addEventListener(type, listener)
  }

  /**
   * 移除事件监听
   */
  removeEventListener(type: string, listener: EventListener): void {
    this.eventBus.removeEventListener(type, listener)
  }
}

2.2 微前端沙箱实现

typescript
// packages/microfrontend/src/sandbox/sandbox.ts

export interface SandboxConfig {
  name: string
  isolateGlobals?: boolean
  isolateStyles?: boolean
  isolateEvents?: boolean
  allowedGlobals?: string[]
  blockedGlobals?: string[]
}

export class Sandbox {
  private config: SandboxConfig
  private originalWindow: Window
  private proxyWindow: Window
  private modifiedGlobals = new Map<string, any>()
  private addedGlobals = new Set<string>()
  private styleElements: HTMLStyleElement[] = []
  private eventListeners: Array<{ element: EventTarget; type: string; listener: EventListener }> = []

  constructor(config: SandboxConfig) {
    this.config = config
    this.originalWindow = window
    this.proxyWindow = this.createProxyWindow()
  }

  /**
   * 激活沙箱
   */
  activate(): Window {
    if (this.config.isolateGlobals) {
      this.activateGlobalIsolation()
    }
    
    if (this.config.isolateStyles) {
      this.activateStyleIsolation()
    }
    
    if (this.config.isolateEvents) {
      this.activateEventIsolation()
    }
    
    return this.proxyWindow
  }

  /**
   * 停用沙箱
   */
  deactivate(): void {
    if (this.config.isolateGlobals) {
      this.deactivateGlobalIsolation()
    }
    
    if (this.config.isolateStyles) {
      this.deactivateStyleIsolation()
    }
    
    if (this.config.isolateEvents) {
      this.deactivateEventIsolation()
    }
  }

  /**
   * 创建代理窗口
   */
  private createProxyWindow(): Window {
    const proxyWindow = new Proxy(this.originalWindow, {
      get: (target, prop) => {
        if (this.isBlockedGlobal(prop as string)) {
          return undefined
        }
        
        if (this.modifiedGlobals.has(prop as string)) {
          return this.modifiedGlobals.get(prop as string)
        }
        
        const value = target[prop as keyof Window]
        
        // 绑定函数的 this 上下文
        if (typeof value === 'function') {
          return value.bind(target)
        }
        
        return value
      },
      
      set: (target, prop, value) => {
        if (this.isBlockedGlobal(prop as string)) {
          return false
        }
        
        // 记录修改的全局变量
        if (prop in target) {
          if (!this.modifiedGlobals.has(prop as string)) {
            this.modifiedGlobals.set(prop as string, target[prop as keyof Window])
          }
        } else {
          this.addedGlobals.add(prop as string)
        }
        
        target[prop as keyof Window] = value
        return true
      },
      
      has: (target, prop) => {
        if (this.isBlockedGlobal(prop as string)) {
          return false
        }
        return prop in target
      }
    })
    
    return proxyWindow
  }

  /**
   * 检查是否为被阻止的全局变量
   */
  private isBlockedGlobal(prop: string): boolean {
    if (this.config.allowedGlobals && !this.config.allowedGlobals.includes(prop)) {
      return true
    }
    
    if (this.config.blockedGlobals && this.config.blockedGlobals.includes(prop)) {
      return true
    }
    
    return false
  }

  /**
   * 激活全局变量隔离
   */
  private activateGlobalIsolation(): void {
    // 全局变量隔离已在代理窗口中实现
  }

  /**
   * 停用全局变量隔离
   */
  private deactivateGlobalIsolation(): void {
    // 恢复修改的全局变量
    for (const [prop, value] of this.modifiedGlobals) {
      this.originalWindow[prop as keyof Window] = value
    }
    
    // 删除添加的全局变量
    for (const prop of this.addedGlobals) {
      delete this.originalWindow[prop as keyof Window]
    }
    
    this.modifiedGlobals.clear()
    this.addedGlobals.clear()
  }

  /**
   * 激活样式隔离
   */
  private activateStyleIsolation(): void {
    // 重写 document.createElement 以拦截 style 元素
    const originalCreateElement = document.createElement
    
    document.createElement = function(tagName: string, options?: ElementCreationOptions) {
      const element = originalCreateElement.call(document, tagName, options)
      
      if (tagName.toLowerCase() === 'style') {
        // 为样式元素添加沙箱标识
        element.setAttribute('data-sandbox', this.config.name)
        this.styleElements.push(element as HTMLStyleElement)
      }
      
      return element
    }.bind(this)
  }

  /**
   * 停用样式隔离
   */
  private deactivateStyleIsolation(): void {
    // 移除沙箱创建的样式元素
    this.styleElements.forEach(element => {
      if (element.parentNode) {
        element.parentNode.removeChild(element)
      }
    })
    
    this.styleElements = []
  }

  /**
   * 激活事件隔离
   */
  private activateEventIsolation(): void {
    // 重写 addEventListener
    const originalAddEventListener = EventTarget.prototype.addEventListener
    
    EventTarget.prototype.addEventListener = function(
      type: string,
      listener: EventListener,
      options?: boolean | AddEventListenerOptions
    ) {
      // 记录事件监听器
      this.eventListeners.push({
        element: this,
        type,
        listener
      })
      
      return originalAddEventListener.call(this, type, listener, options)
    }.bind(this)
  }

  /**
   * 停用事件隔离
   */
  private deactivateEventIsolation(): void {
    // 移除沙箱添加的事件监听器
    this.eventListeners.forEach(({ element, type, listener }) => {
      element.removeEventListener(type, listener)
    })
    
    this.eventListeners = []
  }
}

3. 状态管理架构

3.1 企业级状态管理

typescript
// packages/state-management/src/store/enterprise-store.ts
import { reactive, computed, watch, ref } from 'vue'
import type { ComputedRef, Ref } from 'vue'

export interface StoreModule<T = any> {
  name: string
  state: T
  getters?: Record<string, (state: T, getters: any, rootState: any) => any>
  mutations?: Record<string, (state: T, payload: any) => void>
  actions?: Record<string, (context: ActionContext<T>, payload: any) => any>
  modules?: Record<string, StoreModule>
}

export interface ActionContext<T> {
  state: T
  getters: any
  commit: (type: string, payload?: any) => void
  dispatch: (type: string, payload?: any) => Promise<any>
  rootState: any
  rootGetters: any
}

export interface StoreOptions {
  strict?: boolean
  devtools?: boolean
  plugins?: StorePlugin[]
}

export interface StorePlugin {
  (store: EnterpriseStore): void
}

export interface Mutation {
  type: string
  payload: any
  timestamp: number
}

export interface Action {
  type: string
  payload: any
  timestamp: number
}

export class EnterpriseStore {
  private _state: any
  private _getters: any = {}
  private _mutations = new Map<string, Function>()
  private _actions = new Map<string, Function>()
  private _modules = new Map<string, StoreModule>()
  private _subscribers: Array<(mutation: Mutation, state: any) => void> = []
  private _actionSubscribers: Array<(action: Action, state: any) => void> = []
  private _options: StoreOptions
  private _committing = false
  private _history: Mutation[] = []
  private _actionHistory: Action[] = []

  constructor(options: StoreOptions & { modules?: Record<string, StoreModule> } = {}) {
    this._options = options
    this._state = reactive({})
    
    // 注册根模块
    if (options.modules) {
      Object.entries(options.modules).forEach(([name, module]) => {
        this.registerModule(name, module)
      })
    }
    
    // 应用插件
    if (options.plugins) {
      options.plugins.forEach(plugin => plugin(this))
    }
  }

  /**
   * 获取状态
   */
  get state(): any {
    return this._state
  }

  /**
   * 获取 getters
   */
  get getters(): any {
    return this._getters
  }

  /**
   * 注册模块
   */
  registerModule(name: string, module: StoreModule): void {
    this._modules.set(name, module)
    
    // 初始化模块状态
    this._state[name] = reactive(module.state)
    
    // 注册 getters
    if (module.getters) {
      this._getters[name] = {}
      Object.entries(module.getters).forEach(([key, getter]) => {
        this._getters[name][key] = computed(() => {
          return getter(this._state[name], this._getters[name], this._state)
        })
      })
    }
    
    // 注册 mutations
    if (module.mutations) {
      Object.entries(module.mutations).forEach(([key, mutation]) => {
        const type = `${name}/${key}`
        this._mutations.set(type, mutation)
      })
    }
    
    // 注册 actions
    if (module.actions) {
      Object.entries(module.actions).forEach(([key, action]) => {
        const type = `${name}/${key}`
        this._actions.set(type, action)
      })
    }
    
    // 注册子模块
    if (module.modules) {
      Object.entries(module.modules).forEach(([subName, subModule]) => {
        this.registerModule(`${name}/${subName}`, subModule)
      })
    }
  }

  /**
   * 注销模块
   */
  unregisterModule(name: string): void {
    if (!this._modules.has(name)) {
      return
    }
    
    // 移除状态
    delete this._state[name]
    
    // 移除 getters
    delete this._getters[name]
    
    // 移除 mutations
    for (const [type] of this._mutations) {
      if (type.startsWith(`${name}/`)) {
        this._mutations.delete(type)
      }
    }
    
    // 移除 actions
    for (const [type] of this._actions) {
      if (type.startsWith(`${name}/`)) {
        this._actions.delete(type)
      }
    }
    
    this._modules.delete(name)
  }

  /**
   * 提交 mutation
   */
  commit(type: string, payload?: any): void {
    const mutation = this._mutations.get(type)
    if (!mutation) {
      throw new Error(`Unknown mutation type: ${type}`)
    }
    
    this._withCommit(() => {
      const [moduleName] = type.split('/')
      mutation(this._state[moduleName], payload)
    })
    
    const mutationRecord: Mutation = {
      type,
      payload,
      timestamp: Date.now()
    }
    
    this._history.push(mutationRecord)
    
    // 通知订阅者
    this._subscribers.forEach(subscriber => {
      subscriber(mutationRecord, this._state)
    })
  }

  /**
   * 分发 action
   */
  async dispatch(type: string, payload?: any): Promise<any> {
    const action = this._actions.get(type)
    if (!action) {
      throw new Error(`Unknown action type: ${type}`)
    }
    
    const [moduleName] = type.split('/')
    const context: ActionContext<any> = {
      state: this._state[moduleName],
      getters: this._getters[moduleName] || {},
      commit: this.commit.bind(this),
      dispatch: this.dispatch.bind(this),
      rootState: this._state,
      rootGetters: this._getters
    }
    
    const actionRecord: Action = {
      type,
      payload,
      timestamp: Date.now()
    }
    
    this._actionHistory.push(actionRecord)
    
    // 通知 action 订阅者
    this._actionSubscribers.forEach(subscriber => {
      subscriber(actionRecord, this._state)
    })
    
    return await action(context, payload)
  }

  /**
   * 订阅 mutation
   */
  subscribe(fn: (mutation: Mutation, state: any) => void): () => void {
    this._subscribers.push(fn)
    
    return () => {
      const index = this._subscribers.indexOf(fn)
      if (index > -1) {
        this._subscribers.splice(index, 1)
      }
    }
  }

  /**
   * 订阅 action
   */
  subscribeAction(fn: (action: Action, state: any) => void): () => void {
    this._actionSubscribers.push(fn)
    
    return () => {
      const index = this._actionSubscribers.indexOf(fn)
      if (index > -1) {
        this._actionSubscribers.splice(index, 1)
      }
    }
  }

  /**
   * 监听状态变化
   */
  watch<T>(
    getter: (state: any, getters: any) => T,
    cb: (value: T, oldValue: T) => void,
    options?: { immediate?: boolean; deep?: boolean }
  ): () => void {
    return watch(
      () => getter(this._state, this._getters),
      cb,
      options
    )
  }

  /**
   * 替换状态
   */
  replaceState(state: any): void {
    this._withCommit(() => {
      Object.assign(this._state, state)
    })
  }

  /**
   * 获取历史记录
   */
  getHistory(): { mutations: Mutation[]; actions: Action[] } {
    return {
      mutations: [...this._history],
      actions: [...this._actionHistory]
    }
  }

  /**
   * 清空历史记录
   */
  clearHistory(): void {
    this._history = []
    this._actionHistory = []
  }

  /**
   * 时间旅行调试
   */
  timeTravelTo(index: number): void {
    if (index < 0 || index >= this._history.length) {
      throw new Error('Invalid history index')
    }
    
    // 重放到指定的 mutation
    const targetMutations = this._history.slice(0, index + 1)
    
    // 重置状态
    this.replaceState({})
    
    // 重新注册模块以恢复初始状态
    for (const [name, module] of this._modules) {
      this._state[name] = reactive({ ...module.state })
    }
    
    // 重放 mutations
    targetMutations.forEach(mutation => {
      const mutationFn = this._mutations.get(mutation.type)
      if (mutationFn) {
        const [moduleName] = mutation.type.split('/')
        mutationFn(this._state[moduleName], mutation.payload)
      }
    })
  }

  /**
   * 确保在提交期间修改状态
   */
  private _withCommit(fn: () => void): void {
    const committing = this._committing
    this._committing = true
    fn()
    this._committing = committing
  }
}

4. 实践练习

练习1:架构设计

typescript
// 设计企业级应用架构
// 1. 定义架构层次和模块
// 2. 实现依赖注入容器
// 3. 设计领域模型
// 4. 实现仓储模式

练习2:微前端实现

typescript
// 实现微前端架构
// 1. 创建主应用框架
// 2. 开发子应用模块
// 3. 实现应用间通信
// 4. 添加沙箱隔离

练习3:状态管理

typescript
// 构建状态管理系统
// 1. 设计状态结构
// 2. 实现模块化管理
// 3. 添加中间件支持
// 4. 实现时间旅行调试

练习4:性能优化

typescript
// 实现性能优化策略
// 1. 代码分割和懒加载
// 2. 缓存策略设计
// 3. 虚拟化技术应用
// 4. 性能监控实现

学习资源

架构设计

微前端

状态管理

作业

  1. 架构设计:设计一个完整的企业级应用架构,包含所有层次和模块
  2. 微前端实现:实现一个简单的微前端系统,包含主应用和两个子应用
  3. 状态管理:构建一个企业级状态管理系统,支持模块化和时间旅行
  4. 性能优化:实现一套完整的性能优化方案,包含各种优化策略
  5. 安全架构:设计应用的安全架构,包含认证、授权和数据保护

下一步学习

明天我们将学习「Element Plus 跨平台开发实践」,包括:

  • 移动端适配策略
  • 桌面应用开发
  • 小程序开发实践
  • 跨平台组件设计
  • 平台特性适配

总结

今天我们深入学习了基于 Element Plus 的企业级应用架构设计:

  1. 架构原则:掌握了企业级应用的设计原则和领域驱动设计
  2. 微前端架构:学习了微前端的设计和实现,包括沙箱隔离
  3. 状态管理:构建了企业级的状态管理系统,支持模块化和调试
  4. 性能优化:了解了大型应用的性能优化策略
  5. 安全考虑:学习了企业级应用的安全架构设计

通过这些学习,你现在能够:

  • 设计可扩展的企业级应用架构
  • 实现微前端架构和沙箱隔离
  • 构建复杂的状态管理系统
  • 应用各种性能优化技术
  • 考虑应用的安全性和可维护性

Element Plus Study Guide