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) ; }
}