前序
面试官迟到了,hr 直接加入线上视频会议, 先说了句抱歉,然后开始闲聊
看你在那边待得挺久的,是什么吸引着你?
在那么这么多年里,你觉得自己的成长痕迹是怎么样的?或者随着不同部门的变更,项目变更,觉得自己能力是个怎么样的变化?
为啥要想着走?
我来说说这边的业务大概是个什么情况
面试官上线了, 也是说了些迟到抱歉的话
前面我也听到你的一些经历描述,我看你也做了性能优化,那你说说看,你是怎么做的?
针对差网络情况,你是怎么做的?
有做过针对低端机型的优化吗?
我看你做了些项目的脚手架,你觉得应该怎么保证项目的质量呢
- 事前 开发阶段,代码规范
- 事中 单元测试,eslint, 代码 review
- 事后 发布后,埋点监控,灰度发布
作为负责人,你怎么设计src/components的下的组件,保证组件复用性,可维护性,可测试性
- 单一职责, 每个组件只做一件事
- 高内聚,低耦合,对外依赖尽可能的少
- 组合由于继承,把逻辑尽可能的抽象出来,通过下面拆分的方式,进行组合层复杂组件,保证各个环节的可测试性,减少一个文件的代码量
- 纯函数 丢到工具文件中
- 通用业务逻辑,丢到自定义hooks中
- 组件拆分,把大组件拆成小组件,分而治之
- 注释、文档不可少
- 所有的修改必须走单测,避免影响到其他功能
来说说这个广告投放吧,你说说都用了哪些手段去帮助业务提效的
你说到了schema,了解过业界都有哪一些低代码平台么,或者用过哪一些么
对于大模型,你有自己安装过,做过参数调优么
没有,看过cherry-studio大模型调用桌面的应用的源码,自己实现了类型的一个
对于AI提效,有做过可落地的方案么
没有了,试了下trae 和cursor,感觉效果不是很好,figma上的资源拉不全, trae代码生成差强人意, AI编辑器还会改动已有的代码,没有落地
你用的是 react 技术栈为主对吧,了解过最新的 react 都做了什么吗?
主要讲了 18 和 19
- 18
- 并发(Concurrent Mode) creatRoot
- 合成事件的变化
- useSyncExternalStore
- useTransition
- useId
- Suspense 支持流式渲染
- useDeferredValue 延迟更新非紧急值
- 19
- 乐观更新
- Suspense 并行改为串行
- useActionState 封装异步操作,返回状态、执行函数和加载状态,简化数据变更和错误处理。 主要用在表单处理
- use + Suspense 捕获 + ErrorBoundary 处理异步接口请求渲染,而且 use 可以在条件语句中调用;这之所以可行,是因为 use Hook 本身不维护状态,它只是一个读取机制,因此不受传统 Hooks 调用顺序的限制。
- ref 可以传递引用,无须 forwardRef
为啥hook不支持在条件语句中调用呢?
hook在组件安装定义的顺序加入到链表中,如果条件语句中调用,那么顺序无法预测,导致hook的顺序错乱
说一下redux的核心设计思想吧
- 单向数据流
- State 是只读的
- 数据修改都是通过纯函数来执行
- 可观测,可预测
- IOC 控制反转
- 发布订阅 dispatch和subscribe
- 中间件扩展功能
你说说自己做过的哪一些难的事情,你是怎么解决的
事后想了下,当时应该这么回答的
- 分析问题,确定问题域边界
- 大胆假设
- 验证假设
- 提出可选方案,评估优劣
- 优化方案
- 制定执行计划
- 定期向上汇报进展
- 结果验证
- 复盘
你觉得自己和那些同样工作经历丰富的人有啥优势
- 深度上, 对于可视化,工程构建,CI/CD,性能优化,工程化,都有比较深入的了解和优化成功案例
- 广度上,还有nodejs, electron, 指纹浏览器,h5, 小程序, next.js, nestjs, vue, angular, 自己又是android出身,大学还搞过php, 单片机C语言,平时无聊还会玩玩python
我们来写写代码吧,你打开本地编辑器,投屏我看着就行,实现一个下拉搜索组件,尽可能的通用
import { Select } from 'antd'
import React from 'react'
import { useEffect } from 'react'
/**
* 下拉搜索组件
* @param {string} value - 输入框的值
* @param {function} onChange - 输入框值改变的回调函数
* @param {function} onSelect - 选中项的回调函数
* @param {() => Promise} api - 请求数据的接口
* @returns
*/
function Search(props) {
const { value, onChange, api, placeholder, optionKey, optionLabelKey, params, onSelect } = props
const queryTimerRef = React.useRef()
const [options, setOptions] = React.useState([])
const handleChange = (e) => {
const { value } = e.target
onChange && onChange(value)
if (!api || !optionKey || !optionLabelKey) {
return
}
if (queryTimerRef.current) {
clearTimeout(queryTimerRef.current)
}
queryTimerRef.current = setTimeout(() => {
api(params).then((res) => {
queryTimerRef.current = 0
// 假设返回数据格式就是{ code: 0, data: [] }
const list = (res.data || []).map((item) => {
return {
value: item[optionKey],
label: item[optionLabelKey]
}
})
setOptions(list)
})
}, 300)
}
const handleSelect = (newValue) => {
onSelect && onSelect(newValue)
}
const handleReset = () => {
onChange && onChange('')
setOptions([])
}
useEffect(() => {
const clickOutFn = () => {
handleReset()
}
window.addEventListener('click', clickOutFn)
return () => {
window.removeEventListener('click', clickOutFn)
}
}, [])
return (
<div className="search">
<input
type="text"
value={value}
placeholder={placeholder}
onChange={handleChange}
onBlur={handleReset}
/>
{!!options.length && <Select options={options} onChange={handleSelect}></Select>}
</div>
)
}
说说你的思路,你是怎么实现这个组件的
- 单一职责原则,先实现输入内容后出现下啦列表的功能,先完成再完美
- 对拓展开放,对修改关闭,定义一些props字段,比如
optionLabelKey,api等等, 保证组件尽可能适应多种场景 - 处理边界情况,比如输入框失去焦点后,下拉列表消失,点击外部区域,下拉列表消失,比如传入的props值或者回调函数不存在时候的处理
- 文档编写,单元测试编写
你有什么问题想问我的吗
hr介入
你现在的工作节奏强度怎么样
我们这边工作强大比较大,早10晚10是常态,碰到大促活动,还需要待到12点
这里hr说了很多,意思就是,我们这边加班比较多,经常需要加班,但是加班是常态,加班是常态,加班是常态!
你有什么问题想问我的吗
下一场面试需要你来现场,可以吧
总结
- 神奇的没有问八股
- 面试官可能迟到了,全程很有耐心,保持歉意的笑容