阅读视图

发现新文章,点击刷新页面。

小红书一面:长达一个小时的拷打😭


前言

兄弟也是好起来了,又又有大厂面试了。


面试过程:

一、自我介绍

这个自我介绍我之前在面试文章中提到过,大家可以翻翻查看。

二、实习经历

面试官看到我目前在一家公司实习,于是让我聊了聊我的业务内容。


三、项目方面

1. 你为什么选用 Tailwind CSS?能说说有什么好处吗?

  • 原子化设计:Tailwind CSS 是一种原子化 CSS 框架,将样式拆分为最小的功能单元,每个类只负责一个特定的样式属性。
  • 开发效率高:像写内联类一样快速编写样式,无需额外创建 CSS 文件。
  • 响应式友好:支持大量响应式类,例如 md:w-1/2lg:w-1/4lg:flex-row 等。
  • 样式隔离性强:在 Vue 单文件组件中使用 Tailwind 类,避免传统 CSS 中的样式冲突问题,比如 TabBar、ShowProducts 等组件各自维护自己的样式。
  • 技术广度体现:其实当时用这个是想展示一下对现代前端工具链的理解。
  • 缺点
    • 学习曲线较陡,需要记忆大量类名和约定;
    • 熟练后开发效率更高。
  • 拓展思考
    • 便于 AI 辅助开发:原子类不依赖嵌套或继承,减少 AI 理解上下文的压力;
    • 降低样式覆盖风险,减少了 CSS 的“层叠”问题和选择器冲突。

2. 你的项目用到了组件懒加载,讲讲好处?

  • 在路由懒加载中使用了组件懒加载,实现 按需加载,只有当用户导航到特定路由时,才会加载相应的组件。
  • 如果不使用懒加载,打包时会把所有页面打包成一个文件,首页一次性加载全部资源,导致加载速度慢,用户体验差。
  • 使用路由懒加载后,首页资源被拆分为多个 chunk 文件(如 app.js, home.js),CSS 同样被拆分。
  • 文章参考链接:前端性能优化
面试官追问:你知道为什么会这样吗?

我当时没回答上来,但后来查资料得知:

  • import() 的调用处被视为代码分割点,被请求模块及其子模块会被分离为独立的 chunk。
  • Webpack 等构建工具识别 import(),并将动态导入的模块单独打包,从而减小初始加载体积。
  • 总体积不变,但首屏加载资源减少,提升用户体验。

3. 聊聊你项目中的动态组件

  • 在实现一个礼物推荐助手时,我需要展示用户提问与 AI 回答。
  • 为此我封装了两个组件:一个是用户消息组件,一个是 AI 回复组件。
  • 每次对话内容存储在一个数组中,根据标志属性判断渲染哪个组件。
  • 最终通过 Vue 内置的 <component> 标签结合 :is 属性实现了动态组件切换。

4. 你实现 keep-alive 的目的,以及和 v-if / v-show 的区别?应用场景?

  • keep-alive 目的
    • 缓存组件状态(如表单输入、滚动位置);
    • 避免组件频繁销毁重建;
    • 减少 API 请求,提高性能和用户体验。
  • 缓存控制
    • 使用 include="cachedComponents" 属性,只缓存设置了 meta.cache = true 的组件。
v-ifv-show 的区别:
对比项 keep-alive v-if v-show
是否保持状态 ✅ 是 ❌ 否 ✅ 是
渲染机制 组件缓存 条件为 false 不渲染 切换 display 属性
性能 切换成本低,适合频繁切换 初始化开销小 切换快,初始渲染全量
适用场景 多 tab 切换、表单缓存 不常切换、复杂组件 高频切换简单元素

5. 自定义图片懒加载怎么实现的?

流程如下:

scrollTop + offsetTop
=> getBoundingClientRect()
=> IntersectionObserver

从手动计算逐步过渡到现代浏览器 API,性能越来越好。

又问:你了解 HTML 中原生的 lazy 吗?能否讲讲?
  • 原生 HTML 支持懒加载:<img loading="lazy"><iframe loading="lazy">
  • 优点:简单易用,无需 JS,现代浏览器原生支持;
  • 缺点:兼容性一般,IE 不支持,功能有限;
  • 定制性不强,更高级的需求建议使用 IntersectionObserver 自定义实现。

6.响应式布局这方面,你是怎么做的?

  1. 我的项目中,有一个商品展示的功能,使用的是wc-waterfall ,动态的绑定gap和cols两个属性,通过生命周期挂载,添加事件监听,根据屏幕的大小,调整相应的值,来实现响应式布局。
  2. 通过@media声明在不同尺寸下微调样式细节
  3. 商城项目,经常用得到商品的展示,所以我会将它封装成一个组件,方便复用

四、场景题

1.setimeout

这个是一个面试经常问到的题目,但是他问的很细

for(var i=0;i<4;i++){
    setTimeout(function(){
        console.log(i);
    },1000)
}
首先问你输出什么?

由于 var i 的声明具有函数作用域(在这里指全局作用域),所有的 setTimeout 回调函数实际上引用的是同一个 i 变量。当定时器触发时(即循环已经结束),i 的值已经是 4,因此所有回调打印的结果都是 4。在整个循环过程中只有一个 i,最后连着输出四个4.

又问大概在什么时候输出: 因为定时器不一定准,所以是大概的时间,可能就会回答在4秒后了,实际上,执行同步代码的循环后,定时器四个任务,相继执行,因为间隔时间很短,所以就很像四个定时器并发了一样,实际上还是一个又一个执行的。在大概一秒后。

如何输出 0 1 2 3呢?

var => let

  • 块级作用域:在每次 for 循环迭代中,都会创建一个新的 i 实例。这些 i 变量被限制在循环体的块级作用域内。
  • 延迟执行的回调函数:每个 setTimeout 回调函数捕获的是它对应的那个特定的 i 实例。因此,当定时器触发并执行回调函数时,它们能够访问到正确的 i 值,而不是所有回调都指向同一个 i
那我想要每隔大概一秒输出一个数字呢?
  1. 当时我想到了是:
for (let i = 0,time=1000; i < 4; i++,time+=1000) {
    setTimeout(function () {
        console.log(new Date())
        console.log(i);
    }, time);
}
2025-05-18T14:14:54.808Z
0
2025-05-18T14:14:55.806Z
1
2025-05-18T14:14:56.814Z
2
2025-05-18T14:14:57.800Z
3
  1. 还有就是使用闭包加立即执行函数了:
for (var i = 0; i < 4; i++) {
    (function (i) {
        setTimeout(function () {
            console.log(i);
        }, 1000*i);
    })(i);
}

  1. 进阶:

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

(async function () {
    for (var i = 0; i < 4; i++) {
        await delay(1000);
        console.log(i);
    }
})();

2. 数组求和

const nestedObj = [1, [2, [3, [4, 5]]], 6, 7], 求和。前几天刚好看到了数组和对象的扁平化,刚好就能用上了,不过面试官好像想让我用更简单的方法,我没想出来。

let sum=0
function flattenObject(obj ) {
    for (const item of obj) {
        if (Array.isArray(item)) {
            flattenObject(item);
        } else {
            sum=sum+item;
        }
    }
    return sum;
}
console.log(flattenObject(nestedObj));// [ 1, 2, 3, 4, 5, 6, 7]

学习点其他简单的方法:

  1. 递归
function sum(arr) {
    return arr.reduce((total, item) => {
        return total + (Array.isArray(item) ? sum(item) : item);
    }, 0);
}

const nestedObj = [1, [2, [3, [4, 5]]], 6, 7];
console.log(sum(nestedObj)); // 输出: 28

结语

面了几家大厂后,也有一些心得:

大厂面试一定是穷追猛打,问到你不会为止。所以有些难题回答不出来也没关系。

而面试其实就是一场表演,大家可以在项目中准备几个亮点,自己演练几遍,在面试时流畅表达出来,体现出自己的深度和思考能力,这才是关键!

❌