阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 微前端架构中的设计模式应用

微前端架构中的设计模式应用

作者:陈川 阅读数:20597人阅读 分类: JavaScript

微前端架构中的设计模式应用

微前端架构将单体前端应用拆分为多个独立、松耦合的子应用,每个子应用可以独立开发、部署和运行。在这种分布式架构中,设计模式的应用尤为重要,它们能帮助解决跨应用通信、状态管理、样式隔离等常见问题。

单例模式在全局状态管理中的应用

微前端架构中,多个子应用可能需要共享全局状态。单例模式确保全局状态唯一且易于访问:

class GlobalState {
  constructor() {
    if (GlobalState.instance) {
      return GlobalState.instance;
    }
    this.state = {};
    GlobalState.instance = this;
  }

  set(key, value) {
    this.state[key] = value;
  }

  get(key) {
    return this.state[key];
  }
}

// 子应用A
const stateA = new GlobalState();
stateA.set('user', { name: 'Alice' });

// 子应用B
const stateB = new GlobalState();
console.log(stateB.get('user')); // { name: 'Alice' }

这种实现方式确保所有子应用访问的是同一个状态实例,避免了状态不一致问题。

发布-订阅模式实现跨应用通信

微前端中,子应用间的通信是关键挑战。发布-订阅模式提供松耦合的解决方案:

class EventBus {
  constructor() {
    this.events = {};
  }

  subscribe(event, callback) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);
  }

  publish(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(callback => callback(data));
    }
  }
}

// 主应用初始化事件总线
window.eventBus = new EventBus();

// 子应用A发布事件
window.eventBus.publish('cart-updated', { items: 5 });

// 子应用B订阅事件
window.eventBus.subscribe('cart-updated', data => {
  console.log('购物车更新:', data);
});

这种模式允许子应用在不直接依赖彼此的情况下进行通信。

策略模式处理多环境配置

不同子应用可能需要不同的环境配置策略:

class ConfigStrategy {
  constructor(strategy) {
    this.strategy = strategy;
  }

  setStrategy(strategy) {
    this.strategy = strategy;
  }

  getConfig() {
    return this.strategy.getConfig();
  }
}

class DevConfig {
  getConfig() {
    return {
      apiBase: 'https://dev.api.example.com',
      debug: true
    };
  }
}

class ProdConfig {
  getConfig() {
    return {
      apiBase: 'https://api.example.com',
      debug: false
    };
  }
}

// 使用示例
const config = new ConfigStrategy(new DevConfig());
console.log(config.getConfig());

// 运行时切换策略
config.setStrategy(new ProdConfig());

外观模式简化微前端API

为子应用提供统一简化的接口:

class MicroFrontendFacade {
  constructor() {
    this.router = new RouterService();
    this.state = new GlobalState();
    this.events = new EventBus();
  }

  navigateTo(app, path) {
    this.router.navigate(app, path);
  }

  getSharedState(key) {
    return this.state.get(key);
  }

  subscribeToEvent(event, callback) {
    this.events.subscribe(event, callback);
  }
}

// 子应用中使用
const mfe = new MicroFrontendFacade();
mfe.navigateTo('checkout', '/cart');
mfe.subscribeToEvent('user-logged-in', user => {
  console.log('用户登录:', user);
});

代理模式实现懒加载

优化子应用加载性能:

class MicroAppProxy {
  constructor(name, loader) {
    this.name = name;
    this.loader = loader;
    this.app = null;
  }

  async mount(container) {
    if (!this.app) {
      this.app = await this.loader();
    }
    return this.app.mount(container);
  }

  unmount() {
    if (this.app) {
      return this.app.unmount();
    }
  }
}

// 使用示例
const checkoutApp = new MicroAppProxy('checkout', () => 
  import('https://example.com/checkout-app.js')
);

document.getElementById('checkout-btn').addEventListener('click', () => {
  checkoutApp.mount(document.getElementById('app-container'));
});

装饰器模式增强子应用功能

在不修改原有代码的情况下扩展功能:

function withAnalytics(App) {
  return class extends App {
    mount(container) {
      console.log(`[Analytics] 开始加载应用: ${this.name}`);
      const startTime = performance.now();
      
      const result = super.mount(container);
      
      const loadTime = performance.now() - startTime;
      console.log(`[Analytics] 应用加载完成, 耗时: ${loadTime}ms`);
      
      return result;
    }
  };
}

// 原始应用类
class CheckoutApp {
  constructor() {
    this.name = 'Checkout';
  }
  
  mount(container) {
    console.log('挂载结账应用');
    // 实际挂载逻辑
  }
}

// 增强后的应用
const EnhancedCheckoutApp = withAnalytics(CheckoutApp);
new EnhancedCheckoutApp().mount(document.body);

组合模式构建应用树

管理复杂的子应用嵌套关系:

class MicroAppComponent {
  constructor(name) {
    this.name = name;
    this.children = [];
  }

  add(child) {
    this.children.push(child);
  }

  remove(child) {
    const index = this.children.indexOf(child);
    if (index !== -1) {
      this.children.splice(index, 1);
    }
  }

  async mount(container) {
    console.log(`挂载 ${this.name}`);
    const appContainer = document.createElement('div');
    appContainer.id = `app-${this.name}`;
    container.appendChild(appContainer);
    
    for (const child of this.children) {
      await child.mount(appContainer);
    }
  }
}

// 使用示例
const dashboard = new MicroAppComponent('dashboard');
const header = new MicroAppComponent('header');
const sidebar = new MicroAppComponent('sidebar');
const mainContent = new MicroAppComponent('main');

dashboard.add(header);
dashboard.add(sidebar);
dashboard.add(mainContent);

// 在main区域添加更多子应用
const productList = new MicroAppComponent('product-list');
const recommendations = new MicroAppComponent('recommendations');
mainContent.add(productList);
mainContent.add(recommendations);

dashboard.mount(document.body);

观察者模式实现样式隔离

class StyleObserver {
  constructor() {
    this.observers = [];
    this.currentApp = null;
  }

  register(app) {
    this.observers.push(app);
  }

  setActiveApp(appName) {
    this.currentApp = appName;
    this.notifyAll();
  }

  notifyAll() {
    this.observers.forEach(app => {
      app.updateStyles(this.currentApp === app.name);
    });
  }
}

class MicroApp {
  constructor(name, styleObserver) {
    this.name = name;
    this.styleObserver = styleObserver;
    this.styleObserver.register(this);
  }

  updateStyles(isActive) {
    if (isActive) {
      document.body.classList.add(`app-${this.name}-active`);
    } else {
      document.body.classList.remove(`app-${this.name}-active`);
    }
  }
}

// 使用示例
const styleObserver = new StyleObserver();
const app1 = new MicroApp('checkout', styleObserver);
const app2 = new MicroApp('dashboard', styleObserver);

// 切换应用时
styleObserver.setActiveApp('checkout');

工厂模式创建子应用实例

class MicroAppFactory {
  static createApp(type) {
    switch (type) {
      case 'react':
        return new ReactMicroApp();
      case 'vue':
        return new VueMicroApp();
      case 'angular':
        return new AngularMicroApp();
      default:
        throw new Error('未知的应用类型');
    }
  }
}

class ReactMicroApp {
  mount(container) {
    console.log('挂载React应用');
    // React应用挂载逻辑
  }
}

class VueMicroApp {
  mount(container) {
    console.log('挂载Vue应用');
    // Vue应用挂载逻辑
  }
}

// 使用示例
const app1 = MicroAppFactory.createApp('react');
const app2 = MicroAppFactory.createApp('vue');

app1.mount(document.getElementById('app1'));
app2.mount(document.getElementById('app2'));

适配器模式整合不同框架子应用

class FrameworkAdapter {
  constructor(app) {
    this.app = app;
  }

  mount(container) {
    // 统一mount接口
    if (this.app.mount) {
      return this.app.mount(container);
    } else if (this.app.init) {
      return this.app.init(container);
    } else if (this.app.bootstrap) {
      return this.app.bootstrap().then(() => {
        this.app.mountComponent(container);
      });
    }
    throw new Error('无法适配的应用接口');
  }

  unmount() {
    // 统一unmount接口
    if (this.app.unmount) {
      return this.app.unmount();
    } else if (this.app.destroy) {
      return this.app.destroy();
    }
    return Promise.resolve();
  }
}

// 使用不同框架的子应用
const reactApp = new ReactMicroApp();
const vueApp = new VueMicroApp();

// 统一接口
const adaptedReactApp = new FrameworkAdapter(reactApp);
const adaptedVueApp = new FrameworkAdapter(vueApp);

// 现在可以使用相同的方式操作不同框架的应用
adaptedReactApp.mount(document.getElementById('react-app'));
adaptedVueApp.mount(document.getElementById('vue-app'));

状态模式管理子应用生命周期

class MicroAppState {
  constructor(app) {
    this.app = app;
  }

  mount() {
    throw new Error('必须实现mount方法');
  }

  unmount() {
    throw new Error('必须实现unmount方法');
  }
}

class NotLoadedState extends MicroAppState {
  mount() {
    console.log(`加载应用: ${this.app.name}`);
    return this.app.load().then(() => {
      this.app.setState(new LoadedState(this.app));
      return this.app.mount();
    });
  }

  unmount() {
    console.log('应用未加载,无需卸载');
    return Promise.resolve();
  }
}

class LoadedState extends MicroAppState {
  mount() {
    console.log(`挂载已加载的应用: ${this.app.name}`);
    // 实际挂载逻辑
    return Promise.resolve();
  }

  unmount() {
    console.log(`卸载应用: ${this.app.name}`);
    // 实际卸载逻辑
    return Promise.resolve();
  }
}

class MicroApp {
  constructor(name) {
    this.name = name;
    this.state = new NotLoadedState(this);
  }

  setState(state) {
    this.state = state;
  }

  mount() {
    return this.state.mount();
  }

  unmount() {
    return this.state.unmount();
  }

  load() {
    console.log(`模拟加载应用: ${this.name}`);
    return new Promise(resolve => setTimeout(resolve, 1000));
  }
}

// 使用示例
const app = new MicroApp('checkout');
app.mount(); // 首次加载并挂载
app.unmount(); // 卸载
app.mount(); // 再次挂载(此时已加载)

备忘录模式实现应用状态快照

class AppMemento {
  constructor(state) {
    this.state = JSON.parse(JSON.stringify(state));
  }

  getState() {
    return this.state;
  }
}

class MicroApp {
  constructor() {
    this.state = {
      user: null,
      preferences: {},
      lastRoute: '/'
    };
  }

  save() {
    return new AppMemento(this.state);
  }

  restore(memento) {
    this.state = memento.getState();
  }

  updateState(newState) {
    this.state = { ...this.state, ...newState };
  }
}

// 使用示例
const app = new MicroApp();
app.updateState({ user: { name: 'Alice' } });

// 创建快照
const snapshot1 = app.save();

app.updateState({ lastRoute: '/checkout' });

// 恢复状态
app.restore(snapshot1);
console.log(app.state); // { user: { name: 'Alice' }, preferences: {}, lastRoute: '/' }

职责链模式处理子应用错误

class ErrorHandler {
  constructor(successor = null) {
    this.successor = successor;
  }

  handle(error, app) {
    if (this.canHandle(error)) {
      return this.process(error, app);
    } else if (this.successor) {
      return this.successor.handle(error, app);
    }
    throw error;
  }

  canHandle() {
    throw new Error('必须实现canHandle方法');
  }

  process() {
    throw new Error('必须实现process方法');
  }
}

class NetworkErrorHandler extends ErrorHandler {
  canHandle(error) {
    return error.message.includes('Network');
  }

  process(error, app) {
    console.log('处理网络错误:', error.message);
    return app.retry();
  }
}

class AuthErrorHandler extends ErrorHandler {
  canHandle(error) {
    return error.message.includes('Auth');
  }

  process(error) {
    console.log('处理认证错误:', error.message);
    window.location.href = '/login';
    return Promise.resolve();
  }
}

class DefaultErrorHandler extends ErrorHandler {
  canHandle() {
    return true;
  }

  process(error) {
    console.error('未处理的错误:', error);
    return Promise.reject(error);
  }
}

// 构建责任链
const errorHandler = new NetworkErrorHandler(
  new AuthErrorHandler(
    new DefaultErrorHandler()
  )
);

// 使用示例
class MicroApp {
  constructor() {
    this.retryCount = 0;
  }

  async mount() {
    try {
      // 模拟可能出错的挂载操作
      if (Math.random() > 0.5) {
        throw new Error('Network error: Failed to fetch');
      }
      console.log('应用挂载成功');
    } catch (error) {
      return errorHandler.handle(error, this);
    }
  }

  retry() {
    this.retryCount++;
    console.log(`重试第 ${this.retryCount} 次`);
    return this.mount();
  }
}

const app = new MicroApp();
app.mount();

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌