1、工程化与架构设计(考察项目管理和架构能力)
1.1 你负责的可视化编排项目中,如何设计组件的数据结构来支持"拖拉拽"功能?如何处理组件间的联动关系?
{components: [{id: 'comp1',type: 'input',position: { x: 100, y: 100 },props: { },connections: [{ target: 'comp2', type: 'data' } ]}],eventBus: new EventEmitter()
}
1.2 你提到使用 Vue 的 render 函数实现可视化编排,能详细讲讲这个实现思路吗?与使用 template 的方案相比有什么优势?
{render(h) {return h('div', {class: 'editor',on: {drop: this.handleDrop}}, this.components.map(comp => {return h(comp.type, {props: comp.props,style: {position: 'absolute',left: `${comp.position.x}px`,top: `${comp.position.y}px`},on: this.createComponentEvents(comp)})}))}
}
1.3 在3D展厅项目中,你们是如何解决大型3D模型加载性能问题的?如何平衡展示效果和加载性能?
const loadModel = async (url, level) => {const loader = new THREE.GLTFLoader();const modelUrl = level === 'high' ? url : url.replace('.glb', '_low.glb');return await loader.loadAsync(modelUrl);
};
const lod = new THREE.LOD();
lod.addLevel(highDetailModel, 0);
lod.addLevel(mediumDetailModel, 50);
lod.addLevel(lowDetailModel, 100);
2、技术深度(考察核心技术掌握程度)
2.1 Vue 相关
const app = new Vue({data: {count: 1},mounted() {this.count = 2;this.$nextTick(() => {console.log(this.$el.textContent);});this.count = 3;}
});
2.2 性能优化:
function handleScroll() {const scrollTop = document.documentElement.scrollTop;this.items.forEach(item => {if (item.offsetTop < scrollTop + window.innerHeight) {item.visible = true;}});
}
window.addEventListener('scroll', handleScroll);
function handleScroll() {if (this.scrollTimer) clearTimeout(this.scrollTimer);this.scrollTimer = setTimeout(() => {requestAnimationFrame(() => {const scrollTop = document.documentElement.scrollTop;const viewportHeight = window.innerHeight;this.items.forEach(item => {const rect = item.getBoundingClientRect();if (rect.top < viewportHeight) {item.visible = true;}});});}, 16);
}
window.addEventListener('scroll', handleScroll, { passive: true });
2.3 算法设计
function arrayToTree(items) {const result = []; const itemMap = {}; items.forEach(item => {itemMap[item.id] = { ...item, children: [] };});items.forEach(item => {const parent = itemMap[item.parentId];if (parent) {parent.children.push(itemMap[item.id]);} else {result.push(itemMap[item.id]);}});return result;
}
3. 工程实践(考察实际问题解决能力)
3.1 在你的项目中,如何处理前端权限控制?包括路由权限和按钮权限。
const router = new VueRouter({routes: [{path: '/admin',component: Admin,meta: { requiresAuth: true,permissions: ['admin']}}]
});router.beforeEach((to, from, next) => {if (to.meta.requiresAuth) {const hasPermission = checkPermissions(to.meta.permissions);if (!hasPermission) {next('/403');}}next();
});
Vue.directive('permission', {inserted(el, binding) {const permission = binding.value;if (!hasPermission(permission)) {el.parentNode.removeChild(el);}}
});
3.2 你们的3D项目是如何做异常监控和性能监控的?
const stats = new Stats();
document.body.appendChild(stats.dom);
window.addEventListener('error', (event) => {if (event.target instanceof HTMLImageElement) {handleResourceError(event);} else {handleRuntimeError(event);}
});
canvas.addEventListener('webglcontextlost', handleContextLost);
canvas.addEventListener('webglcontextrestored', handleContextRestored);
3.3 在多人协作的项目中,你们是如何确保代码质量的?具体的工程化措施有哪些?
4. 技术视野(考察技术广度和思维方式)
4.1 Vue2 到 Vue3 的升级中,你认为最重要的变化是什么?这些变化解决了什么问题?
4.2 对比 Webpack 和 Vite,你认为它们各自的优势是什么?在什么场景下选择使用?
4.3 前端微服务架构中,你认为最关键的技术挑战是什么?如何解决?
5.项目管理(考察管理能力)
5.1 作为项目经理,你是如何评估项目风险的?能举个具体的例子吗?
5.2 在带领团队时,你是如何进行技术选型和技术架构决策的?
5.3 如何平衡项目进度和代码质量?
6.实战题目(考察实际编码能力)
6.1 手写题
class EventEmitter {on(event, callback) {}emit(event, ...args) {}off(event, callback) {}once(event, callback) {}
}
class EventEmitter {constructor() {this.events = new Map();}on(event, callback) {if (!this.events.has(event)) {this.events.set(event, []);}this.events.get(event).push(callback);}emit(event, ...args) {if (this.events.has(event)) {this.events.get(event).forEach(callback => {callback.apply(this, args);});}}off(event, callback) {if (this.events.has(event)) {const callbacks = this.events.get(event);const index = callbacks.indexOf(callback);if (index !== -1) {callbacks.splice(index, 1);}}}once(event, callback) {const wrapper = (...args) => {callback.apply(this, args);this.off(event, wrapper);};this.on(event, wrapper);}
}
6.2 设计题
class Cache {constructor(options = {}) {this.storage = options.storage || new MemoryStorage();this.maxSize = options.maxSize || 1000;this.cleanupInterval = options.cleanupInterval || 60000;this.startCleanup();}async set(key, value, options = {}) {const item = {value,priority: options.priority || 0,expires: options.expires ? Date.now() + options.expires : null,size: this.getSize(value)};await this.ensureSpace(item.size);await this.storage.set(key, item);}async get(key) {const item = await this.storage.get(key);if (!item) return null;if (item.expires && item.expires < Date.now()) {await this.storage.delete(key);return null;}return item.value;}private async ensureSpace(requiredSize) {const currentSize = await this.getCurrentSize();if (currentSize + requiredSize <= this.maxSize) return;const items = await this.getAllItems();items.sort((a, b) => {if (a.priority !== b.priority) return a.priority - b.priority;return (a.expires || Infinity) - (b.expires || Infinity);});let freedSpace = 0;for (const item of items) {if (currentSize - freedSpace + requiredSize <= this.maxSize) break;await this.storage.delete(item.key);freedSpace += item.size;}}private startCleanup() {setInterval(async () => {const items = await this.getAllItems();const now = Date.now();for (const item of items) {if (item.expires && item.expires < now) {await this.storage.delete(item.key);}}}, this.cleanupInterval);}
}