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. 性能监控实现
学习资源
架构设计
微前端
状态管理
作业
- 架构设计:设计一个完整的企业级应用架构,包含所有层次和模块
- 微前端实现:实现一个简单的微前端系统,包含主应用和两个子应用
- 状态管理:构建一个企业级状态管理系统,支持模块化和时间旅行
- 性能优化:实现一套完整的性能优化方案,包含各种优化策略
- 安全架构:设计应用的安全架构,包含认证、授权和数据保护
下一步学习
明天我们将学习「Element Plus 跨平台开发实践」,包括:
- 移动端适配策略
- 桌面应用开发
- 小程序开发实践
- 跨平台组件设计
- 平台特性适配
总结
今天我们深入学习了基于 Element Plus 的企业级应用架构设计:
- 架构原则:掌握了企业级应用的设计原则和领域驱动设计
- 微前端架构:学习了微前端的设计和实现,包括沙箱隔离
- 状态管理:构建了企业级的状态管理系统,支持模块化和调试
- 性能优化:了解了大型应用的性能优化策略
- 安全考虑:学习了企业级应用的安全架构设计
通过这些学习,你现在能够:
- 设计可扩展的企业级应用架构
- 实现微前端架构和沙箱隔离
- 构建复杂的状态管理系统
- 应用各种性能优化技术
- 考虑应用的安全性和可维护性