写在前面:面经只是记录博主遇到的题目。每题的答案在编写文档的时候已经有问过deepseek,它只是一种比较普世的答案,要学得深入还是靠自己
Q:手撕代码,两个有序数组排序
A:
function mysort(arr1, arr2) {let i = 0;let j = 0;let res = [];while (i < arr1.length && j < arr2.length) {if (arr1[i] <= arr2[j]) {res.push(arr1[i])i++} else {res.push(arr2[j])j++}}return [...res, ...arr1.slice(i), ...arr2.slice(j)];
}
Q:Vue里emit和on如何实现“发起然后更新”这样一个过程
A:
- $emit: 用于触发/发起一个自定义事件
- $on: 用于监听/订阅一个自定义事件
父子组件之间:子组件发起(emit),父组件监听(on)并更新
<!-- 子组件 Child.vue -->
<template><button @click="sendMessage">发送消息</button>
</template><script>
export default {methods: {sendMessage() {// 发起/触发一个名为'message-sent'的事件,并附带数据this.$emit('message-sent', { text: 'Hello from child!' });}}
}
</script>
<!-- 父组件 Parent.vue -->
<template><div><child @message-sent="handleMessage"></child><p>收到的消息: {{ receivedMessage }}</p></div>
</template><script>
import Child from './Child.vue';export default {components: { Child },data() {return {receivedMessage: ''};},methods: {// 监听/处理子组件发出的事件handleMessage(payload) {this.receivedMessage = payload.text; // 更新数据console.log('收到消息:', payload.text);}}
}
</script>
Q:一个平铺数组如何变成树
A:
const flatArray = [{ id: 1, pid: 0, children: [{ id: 2, pid: 1, children: null }] },{ id: 3, pid: 0, children: null }
];function normalizeTree(node) {if (node.children === null) {node.children = [];} else if (Array.isArray(node.children)) {node.children.forEach(normalizeTree);}return node;
}const tree = flatArray.map(normalizeTree);
console.log(tree);
Q:Nuxt.js有了解吗
A:一个基于Vue.js的SSR服务端渲染和静态站点生成的SSG框架,用于构建高性能、SEO友好的现代web应用,它简化了Vue.js的开发流程。
核心:多种渲染模式,服务端渲染,静态站点生成,单页应用,混合渲染。
无需手动vue-router,内置代码分割,预加载,支持HMR。
适合博客、电商、后台管理系统、全栈应用。
Q:代码分割是为了什么,在什么场景下用
A:
- ESM代码分割:() => import(组件),实现动态引入。
- WebPack代码分割:需要性能优化的场景下使用,减少包体积,给浏览器缓存,包分得多了,如果只改一部分js代码,就不需要整个js重新加载。
WebPack分割配置:
// webpack.config.js
module.exports = {// ...optimization: {splitChunks: {chunks: 'all', // 对所有模块进行优化(包括同步和异步)minSize: 20000, // 生成 chunk 的最小体积(20KB)minRemainingSize: 0,minChunks: 1, // 被引用次数 >=1 才会被拆分maxAsyncRequests: 30, // 最大异步请求数(默认 30)maxInitialRequests: 30, // 入口点的最大并行请求数(默认 30)enforceSizeThreshold: 50000, // 强制拆分阈值(50KB)cacheGroups: {// 拆分第三方库(node_modules)vendors: {test: /[\\/]node_modules[\\/]/,priority: -10, // 优先级reuseExistingChunk: true,name: 'vendors', // 输出文件名(如 vendors.js)},// 拆分公共代码(被多个入口引用)common: {minChunks: 2, // 至少被 2 个入口引用priority: -20,reuseExistingChunk: true,name: 'common', // 输出文件名(如 common.js)},},},},
};
Q:v-model如何实现的
A:它实现了表单输入和应用状态之间的双向数据绑定。本质上是语法糖,结合了数据绑定和事件监听。
<custom-input v-model="message"></custom-input>
// 相当于是 v-bind + v-on 的语法糖
<custom-input :value="message" // 将 value 属性绑定到 Vue 实例的 message 数据@input="message = $event.target.value" // 监听 input 事件,当输入值变化时更新 message
></custom-input>// 组件内部需要:
// 接收 value 这个prop
// 在值变化时触发 input 事件
Vue.component('custom-input', {props: ['value'],template: `<input:value="value"@input="$emit('input', $event.target.value)">`})
底层实现机制:
模板编译:Vue 编译器将模板中的 v-model 转换为 v-bind:value 和 v-on:input
AST 转换:生成抽象语法树时处理 v-model 指令
数据绑定:通过 Object.defineProperty 或 Proxy 实现响应式
事件监听:建立事件监听器,在事件触发时更新数据