自我介绍
....
你说你过这个首屏优化,你是怎么做的,最终效果如何
把首屏优化看成是一个大问题,对问题进行抽象、分层和分治
- 缓存
- 强缓存
- 协商缓存
- pwa
- cdn
- 客户端缓存
- 网络链路
- DNS
- TCP/UDP
- SSL/TLS
- HTTP
- 渲染
- html
- 预渲染
- DNS 预解析
- 压缩
- css
- 拆分动态加载
- 压缩
- js
- 通用
- 业务
- 首次加载必须
- 非首次加载必须
- 其他资源
- 图片
- 懒加载
- 预加载
- 渐进式加载
- 压缩
- 动画文件 SVGA
- 预加载
- 图片
- html
最后效果:首屏时间 2s,T95 线达标
你简历上这个多业务线模版规范,你是怎么做的
业务背景....
还有什么项目能和我说说么
那就说下复杂度比较高的数据平台吧...(对方围着着这里又问了几个问题)
你这个广告投放项目的动态联动表单是怎么做的
实现一个 JSON Schema 的表单生成器,然后通过 JSON Schema 生成表单...
能举个例子么
。。。
还有什么项目能和我说说么
说一下海外投放的指纹浏览器吧。。。
那么我们来考考一些基础吧,常用的 react hook 有哪一些
useState,useEffect,useContext,useReducer,useCallback,useMemo,useRef,useImperativeHandle
useCallback,useMemo 有啥区别
useCallback 返回一个 memoized 回调函数,useMemo 返回一个 memoized 值
useState 里面放置一个函数,会怎么样
会执行这个函数,然后返回执行结果作为初始化值
// React 内部 useState 实现(简化版本)
function useState(initialState) {
// 获取当前 Hook 索引的 Fiber 节点上的状态
const hook = getHook()
if (!hook) {
// 如果是第一次渲染,初始化 Hook,并设置初始状态
hook = {
state: typeof initialState === 'function' ? initialState() : initialState,
queue: []
}
mountHook(hook)
}
// 返回状态和用于更新状态的函数
const setState = (action) => {
// 将新状态入队
const newState = typeof action === 'function' ? action(hook.state) : action
hook.state = newState
// 触发组件的重新渲染
scheduleUpdate()
}
return [hook.state, setState]
}
什么是受控和非受控组件
平时项目都用什么第三方库
- antd
- g2
- g6
- echarts
- lodash
- moment
- axios
- days ...
那我们就来说说 antd form 组件是怎么拿到 input 控件的 value 值的
来做做题吧,题 1, 实现一个高阶组件,CheckPropsWrapper(Comp, schema), schema 是一个 yua 库生成的对象,用于校验 props 的值是不是合法,newPropOrErr = schema.validate({ name: 'key' }),如果 err 为空,抛出错误,否则返回 Comp 组件, 注意 newPropOrErr 可能是修正后的值,需要传入给 Comp 组件
function CheckPropsWrapper(Comp: any, schema: any) {
return function (props: any) {
const obj = useMemo(() => {
const newProps: Record<string, any> = { ...props }
const errs = []
for (const key in props) {
try {
const newPropOrErr = schema.validate({ [key]: props[key] })
newProps[key] = newPropOrErr[key]
} catch (e: any) {
errs.push(e.message)
}
}
console.log(newProps, errs)
return {
props: newProps,
errs
}
}, [props])
return obj.errs.length ? <div>{obj.errs.join(',')}</div> : <Comp {...obj.props} />
}
}
function TestComp(props: any) {
return <div>{props.name}</div>
}
const RightTestComp = CheckPropsWrapper(TestComp, {
validate(obj: Record<string, any>) {
if (obj.name === 'test') {
return {
...obj,
name: 'hello'
}
}
return new Error('name is not test')
}
})
2025 年了怎么判断 error
const error = new Error('error')
console.log(error instanceof Error) // true
console.log(toString.call(error) === '[object Error]') // true
(你倒是说 2025 年了怎么判断 error 啊,然后对方跳过了)
上面的 Comp 如果打印拿到的是什么东西
VNODE对象,对方觉得不对,我线下试了下,如果传入的是一个hook组件,则是一个渲染函数里面包含了react.createElement,如果是class组件,则是一个class组件实例
题目二,实现一个 hook,[ref, hovering] = useHover()
function useHover() {
const [hovering, setHovering] = useState(false)
const ref = useRef(null)
useEffect(() => {
const node = ref.current
if (node) {
const handleMouseOver = () => setHovering(true)
const handleMouseOut = () => setHovering(false)
node.addEventListener('mouseover', handleMouseOver)
node.addEventListener('mouseout', handleMouseOut)
return () => {
node.removeEventListener('mouseover', handleMouseOver)
node.removeEventListener('mouseout', handleMouseOut)
}
}
}, [])
return [ref, hovering]
}
useRef 有啥使用场景
题目三,实现下面ts的类型,<table data={[{ a: '1', b: '2', c: '3' }]} columns={[{ title: 'a', dataIndex: 'a' }, { title: 'b', dataIndex: 'b' }, { title: 'c', dataIndex: 'c' }]}> >
- 方式一
```ts
type TableDataRow<T> = {
[P in keyof T]: T[P]
}
type TableColumn<T> = {
title: string
dataIndex: keyof TableDataRow<T>
}
type TableProps<T> = {
data: TableDataRow<T>[]
columns: TableColumn<T>[]
}
type Row = {
name: string
age: number
}
const tableProps: TableProps<Row> = {
data: [{ name: '1', age: 18 }],
columns: [{ title: 'name', dataIndex: 'name' }]
}
- 方式二
type TableProps<T> = {
data: T[]
columns: {
title: string
dataIndex: keyof T
}[]
}
const data = { name: '1', age: 18 }
const tableProps: TableProps<typeof data> = {
data: [data],
columns: [{ title: 'name', dataIndex: 'name' }]
}
方式三
type TableDataRow<T> = Record<string, T>
type TableColumn<D> = {
title: string
dataIndex: keyof D
}
type TableProps<T, D> = {
data: TableDataRow<T>[]
columns: TableColumn<D>[]
}
const data = [{ name: '1', age: 18 }]
const tableProps1: TableProps<string | number, typeof data[0]> = {
data,
columns: [{ title: 'name', dataIndex: 'name' }]
}
> 怎么限制T 只能是string|number
忘了
> ts 中never,void,unknown 的区别
只说了void,never,unknown不知道
- nerver
- 一个从来不会有返回值的函数,即死循环
- 一个总是会抛出错误的函数
- void 没有返回值的函数
- unknown
- any类型相似,但更安全,因为对未知值做任何事情都是不合法的。
- 需要通过类型范围缩小或类型断言,才能在 unknown 类型上进行任何操作
> 有什么想问的么
进去干啥之类的,反正你也不会说
## 总结
都二面了,不应该问问框架原理么,咋抓住语法糖不放过...,还有手写代码时候,面试官可能是个ts类型体操重度患者,看你用js写,就不断diss你,不是大哥,我写的是js,不是ts...