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