MST
星途 面试题库

面试题:TypeScript 访问修饰符与封装原则在复杂架构中的深度应用

在一个基于微前端架构的 TypeScript 项目中,不同的微前端应用之间存在复杂的交互和依赖关系。请结合访问修饰符与封装原则,设计一套安全且高效的通信机制,既要保证各个微前端内部数据和逻辑的封装性,又要满足它们之间必要的交互需求,详细描述设计思路、关键代码结构以及如何处理可能出现的跨域和访问权限问题。
49.9万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 封装原则:利用 TypeScript 的类和模块系统,将每个微前端应用的内部数据和逻辑封装在类中,通过访问修饰符(如 privateprotected)来限制外部对内部数据的直接访问。例如,将敏感数据设为 private,只暴露必要的公共方法来操作这些数据。
  2. 通信机制:采用事件总线模式,创建一个全局的事件总线类,各个微前端应用通过注册事件监听器和触发事件来进行通信。这样可以解耦不同微前端之间的直接依赖关系。
  3. 跨域问题:使用代理服务器来解决跨域问题。在开发环境中,可以使用工具(如 webpack-dev-server 的 proxy 配置)进行代理转发。在生产环境中,配置服务器端(如 Nginx)进行反向代理,将跨域请求转发到目标微前端应用所在的服务器。
  4. 访问权限问题:在事件总线的基础上,添加权限验证逻辑。例如,在触发事件时,检查当前微前端应用是否具有触发该事件的权限。可以通过在事件注册时,为每个事件绑定权限标识,在触发事件前进行权限检查。

关键代码结构

  1. 事件总线类
class EventBus {
    private events: { [eventName: string]: Array<(data: any) => void> } = {};

    // 注册事件监听器
    on(eventName: string, callback: (data: any) => void) {
        if (!this.events[eventName]) {
            this.events[eventName] = [];
        }
        this.events[eventName].push(callback);
    }

    // 触发事件
    emit(eventName: string, data: any) {
        if (this.events[eventName]) {
            this.events[eventName].forEach(callback => callback(data));
        }
    }
}

// 创建全局事件总线实例
const globalEventBus = new EventBus();
  1. 微前端应用示例
class MicroFrontend {
    private internalData: string;

    constructor() {
        this.internalData = 'private data';
        // 注册事件监听器
        globalEventBus.on('message-from-other', (data) => {
            console.log(`Received message: ${data}`);
        });
    }

    // 暴露公共方法来触发事件
    public sendMessageToOther(data: string) {
        globalEventBus.emit('message-to-other', data);
    }
}

处理跨域和访问权限问题

  1. 跨域处理
    • 开发环境:在 webpack.config.js 中配置 proxy:
module.exports = {
    //...其他配置
    devServer: {
        proxy: {
            '/api': {
                target: 'http://target - micro - frontend - url',
                changeOrigin: true
            }
        }
    }
};
- **生产环境**:在 Nginx 配置文件中添加反向代理规则:
server {
    listen 80;
    server_name your - domain.com;

    location /api {
        proxy_pass http://target - micro - frontend - url;
        proxy_set_header Host $host;
        proxy_set_header X - Real - IP $remote_addr;
        proxy_set_header X - Forwarded - For $proxy_add_x_forwarded_for;
        proxy_set_header X - Forwarded - Proto $scheme;
    }
}
  1. 访问权限处理
    • 权限标识绑定:修改事件总线类,为事件添加权限标识。
class EventBus {
    private events: { [eventName: string]: { permission: string, callbacks: Array<(data: any) => void> } } = {};

    // 注册事件监听器
    on(eventName: string, permission: string, callback: (data: any) => void) {
        if (!this.events[eventName]) {
            this.events[eventName] = { permission, callbacks: [] };
        }
        this.events[eventName].callbacks.push(callback);
    }

    // 触发事件
    emit(eventName: string, data: any, currentPermission: string) {
        if (this.events[eventName] && this.events[eventName].permission === currentPermission) {
            this.events[eventName].callbacks.forEach(callback => callback(data));
        }
    }
}

// 创建全局事件总线实例
const globalEventBus = new EventBus();
- **权限检查**:在微前端应用中,触发事件前进行权限检查。
class MicroFrontend {
    private internalData: string;
    private myPermission: string = 'allowed - permission';

    constructor() {
        this.internalData = 'private data';
        // 注册事件监听器
        globalEventBus.on('message - from - other', 'allowed - permission', (data) => {
            console.log(`Received message: ${data}`);
        });
    }

    // 暴露公共方法来触发事件
    public sendMessageToOther(data: string) {
        globalEventBus.emit('message - to - other', data, this.myPermission);
    }
}