针对你 1.5 年的前端经验,结合 Vue 3、TypeScript、微前端(qiankun)等背景,我准备了一套模拟面试题,偏向场景化问题,考察你的实战经验和思维能力。
一、工程化 & 架构
- 你们的前端项目使用 qiankun 做微前端,但有子应用加载很慢,该如何优化?
考察点:微前端性能优化、懒加载、资源预加载等
- 你负责的 Vue 3 项目需要引入 Ant Design 组件库,但业务场景只用到少部分组件,你如何优化打包大小?
考察点:按需加载、tree shaking、unplugin-vue-components
- 团队发现目前的业务代码复用度不高,你如何设计一个可复用的业务组件库?
考察点:组件封装、dumi 文档管理、npm 发布等
二、Vue 3 & 组件通信
- 在 Vue 3 里,你要在 setup 之外的地方访问 ref 或 computed,该如何处理?
考察点:toRef、toRaw、getCurrentInstance、Pinia
- 你有一个 Vue 组件 A,B 组件是它的子组件,要求 A 组件能在不刷新页面的情况下实时监听 B 组件的某个数据变化,你会如何实现?
考察点:defineModel、watch、provide/inject、事件总线
- 在 Vue 3 组合式 API 中,你如何在子组件 onUnmounted 时,通知父组件进行某些操作?
考察点:onUnmounted、emit、expose、事件总线
三、前端性能优化
- 你在分析一个 Vue 3 页面,发现某个 computed 执行次数过多,如何优化?
考察点:依赖收集、shallowRef、triggerRef
- 你在一个复杂表单里发现输入有明显卡顿,该如何排查并优化?
考察点:防抖、节流、v-model.lazy、vueuse 的 useDebounceFn
- 你的团队希望对 Vue 3 项目进行骨架屏优化,该如何实现?
考察点:骨架屏组件封装、suspense、IntersectionObserver 预加载
四、微前端 & 跨应用通信
- 你在 qiankun 里如何实现主应用和子应用的跨应用状态同步?
考察点:props 传递、qiankun 的全局状态、localStorage/sessionStorage
- 微前端子应用 A 需要跳转到子应用 B 的某个页面,但要求 URL 结构保持一致,如何实现?
考察点:qiankun 的路由同步、activeRule 机制、history.pushState
五、综合场景
- 你的 Vue 3 项目在用户访问某个页面时,白屏时间过长,你如何排查并优化?
考察点:懒加载、骨架屏、路由异步组件、performance API 监控
- 你在 Vue 3 组件里用了 watchEffect 监听某个变量,但发现它执行了不必要的副作用,如何优化?
考察点:watch vs watchEffect、flush 选项
- 你们的前端项目需要支持动态权限控制,不同用户访问同一页面展示不同内容,如何设计?
考察点:路由权限、组件权限、前后端协作
answer:
下面是所有问题的详细回答,包括思路分析、代码示例和优化建议。
一、工程化 & 架构
- 你们的前端项目使用 qiankun 做微前端,但有子应用加载很慢,该如何优化?
分析:
子应用加载慢可能由多个因素导致,如资源体积过大、网络请求过多、首屏渲染慢等,优化可以从以下几个方面入手:
- 减少子应用打包体积
采用 按需加载(import())
组件库 Tree Shaking(如 Ant Design Vue 用 unplugin-vue-components)
使用 gzip 或 brotli 压缩
通过 CDN 加载第三方库(externals 配置)
- 优化子应用的资源加载
开启 HTTP/2
预加载核心资源()
缓存优化(使用 service worker / cache-control)
- 优化首屏渲染
Skeleton 骨架屏
异步数据请求
路由懒加载
子应用内 SSR(如 Nuxt / Vite SSR)
- 使用 qiankun 预加载机制
prefetch 机制提前加载:
registerMicroApps(apps, {
prefetch: true, // 预加载
});
手动预加载:
import { loadMicroApp } from ‘qiankun’;
const microApp = loadMicroApp({
name: ‘child-app’,
entry: ‘http://child-app.com’,
container: ‘#child-container’
});
- 你负责的 Vue 3 项目需要引入 Ant Design 组件库,但业务场景只用到少部分组件,你如何优化打包大小?
解决方案:
- 使用 unplugin-vue-components 自动按需导入:
import Components from ‘unplugin-vue-components/vite’;
import { AntDesignVueResolver } from ‘unplugin-vue-components/resolvers’;
export default defineConfig({
plugins: [
Components({
resolvers: [AntDesignVueResolver()], // 自动引入
}),
],
});
- 避免全量引入
import { Button } from ‘ant-design-vue’;
app.use(Button);
- 使用 ES 模块方式导入
import ‘ant-design-vue/es/button/style/css’;
- 你如何设计一个可复用的业务组件库?
关键点:
封装通用组件
使用 dumi 生成文档
打包并发布至 npm
步骤:
- 封装组件
- 使用 dumi 生成组件文档
npm install dumi -D
- 使用 Rollup/Vite 打包
npm publish
二、Vue 3 & 组件通信
- 在 Vue 3 里,你要在 setup 之外的地方访问 ref 或 computed,该如何处理?
方法 1:使用 getCurrentInstance
import { getCurrentInstance } from ‘vue’;
const instance = getCurrentInstance();
console.log(instance.proxy.someRef);
方法 2:使用 toRef 和 toRaw
const state = reactive({ count: 0 });
const countRef = toRef(state, ‘count’);
- 组件 A 监听 B 组件的数据变化
方法 1:defineModel
方法 2:watch 监听 Props
watch(() => props.value, (newVal) => { console.log(newVal); });
方法 3:provide/inject
provide(‘key’, value);
const injectedValue = inject(‘key’);
- 在 Vue 3 组件 onUnmounted 时通知父组件
方法:emit 事件
三、前端性能优化
- computed 执行次数过多
优化方案:
使用 shallowRef
const state = shallowRef({ value: 1 });
使用 triggerRef 手动触发更新
triggerRef(state);
- 复杂表单输入卡顿
优化方案:
使用 v-model.lazy
防抖
import { useDebounceFn } from ‘@vueuse/core’;
const updateValue = useDebounceFn((val) => console.log(val), 300);
- 骨架屏
方案:
四、微前端 & 跨应用通信
- qiankun 主应用与子应用状态同步
方法 1:使用 props
registerMicroApps([{ props: { globalState } }]);
方法 2:使用 qiankun 的 initGlobalState
const actions = initGlobalState({ user: ‘admin’ });
actions.setGlobalState({ user: ‘guest’ });
- 微前端子应用 A 跳转子应用 B,URL 保持一致
history.pushState({}, ‘’, ‘/sub-app-b’);
五、综合场景
- Vue 3 页面白屏时间长,如何优化?
优化方案:
- 路由懒加载
const Component = defineAsyncComponent(() => import(’./Component.vue’));
-
骨架屏
-
异步数据处理
- watchEffect 监听不必要的副作用
优化方案:
watch(() => props.value, (newVal) => { console.log(newVal); });
- 动态权限控制
方法:
const userPermissions = ref([‘view_dashboard’]);
const hasPermission = computed(() => userPermissions.value.includes(‘view_dashboard’));
Dashboard