面试题目汇总
react篇
React生命周期
挂载时 constructor getDerivedStateFromProps render componentDidMount
更新 getDerivedStateFromProps scu render getSnapBeforeUpdate didUpdate
卸载 willUnmount
willmount willupdate willReceiveProps 异步渲染 渲染可以被中断
React版本差异
16.3 引入fiber结构
16.8 引入hooks
17 全新的jsx转换 babel->react.createElement -> react.jsx
事件委托层 document -> container
去除事件池
18 自动批量更新处理 非紧急更新transition concurrent
react脚手架选择 next remix gastby
react合成事件 帮助用户解决了平台兼容性 事件委托等优化机制 17前放在document上 之后放在container上
jsx是什么 17之后变成了package种引入新的入口函数(_jsx)并调用 旧的createElement也能用
jsx调度机制 react实现单线程调度机制 采用最小堆数据结构 在时间切片内循环执行任务 如果重新调度这样避免高优先级任务因为迟迟得不到处理的问题 任务执行顺序取决于优先级和过期时间
时间切片 时间轮询 规定时间内执行任务 调度器周期性的执行任务 15ms requestAnimationFrame
Fiber是什么 是vDOM的表现形式 传统的vdom 父节点子节点都是数组 遍历的方式自上而下自左边到右 fiber的结构是链表结构child, return sibling属性 有利于中断任务执行
vDOM js对象 相对于DOM对象,js对象处理起来更快,而且更简单。通过diff算法对比新旧vdom之间的差异,可以批量的、最小化的执行dom操作
context原理用法 用法:createContext -> provider传递value -> 后代组件消费value 函数组件用useContext 原理context存储结构和hooks类似都是单链表结构 检查新老context有无变化 value的值用栈管理
react vs vue diff算法 vue的vdom主要是文本 数组 React则是文本单个节点 vue当中new vdom是数组 双端查找遍历 React则是链表结构 从左向右历 React是吧老的链表都建成valueHashMap vue则是新的链表构建成了key:indexhashMap,获取剩下节点的最长递增子序列
vue3中的Diff算法:
1. newVdom是文本 1.1老的是数组不匹配 直接删除 1.2newVom!==oldVdom 修改文本
2. newVdom不是文本 2.1oldVdom不数组是文本 直接删除 newVdom是数组 那就是新增节点 2.2oldVdom是数组 newVdom不是数组也不是文本 表示没有新节点 2.2 oldVdom数组 先从左向右 如果遇到节点不能复用就截止 2.3 然后从右向左 如果遇到节点不能复用就截止 2.4老节点没了直接新增新节点 2.5新节点没了 删除老节点 2.6 遍历老节点的根据将新节点做成map图(值是新节点的index key是老节点)看是否有节点可以复用 判断节点是否需要移动位置 遍历新节点 是否是LIS 这些节点不同 少数移动或删除
React的Diff
老的是链表结构 新的可能是element 文本 数组等
newVdom文本节点<div>ttt<a></a></div>
老的也是文本节点 删掉老节点的兄弟节点 复用文本节点 更新内容 返回这个Fiber
老的不是文本节点 全部删除 创建新的文本节点
当前是更新阶段 并且newFiber.alert为null 则添加placement 标记这个节点为新增
newVdom是单个节点
1.循环遍历老节点对key和类型与老节点比较 遍历过程中 oldVom单节点 同一层下相同key值相同类型 如果是fragment节点 则把老fragment后面的Fiber节点杀出 并且复用这个fragment 返回复用之后的得到的Fiber 不是fragment 新老节点类型相同则把这个老节点后面的几点全部删除 并且复用这个老节点的Fiber 返回复用之后得到的Fiber 类型不同删除剩余接地那 终止循环 2.老节点循环结束 如果新节点是fragment 创建fragment Fiber 执行createFiberFromElment
newVdom是数组
从左向右比较新老节点 如果节点可以复用 就继续不行就停止
新节点没了 老节点还有 则删除剩余节点
新节点还有 老节点没了 初次渲染没有老节点 更新阶段 老节点已经匹配完成
都还有 剩下的单链表创建map 遍历新节点 对应完了找到复用的 剩余就删除了
lazy 传入一个load函数 只会被执行一次
react-router6 利用context机制 在browserrouter或者hashRouter利用useLayoutEffect做了一层路由监听
React Router中history、hash路由差异
监听onHashChange事件 #之后字符变化 因此前端根据这个变化决定渲染那个租金啊
BrowerRouter使用html5 history api(pushState replaceState和popState事件)让页面UI
前端路由如何切换页面 historyRouter hashRouter memoryRouter (createBrowserHistory, createHashHistory,createMemoryHistory) 然后使用useLayoutEffect监听setState在组建卸载取消监听
前端路由带来什么 1. 不涉及HTML页面跳转 2 只涉及到组件之间的转换 3 页面效果更好 4 组件开发边界 但是也有缺点 首屏加载慢 不利于seo 页面复杂度提高
Hooks解决的问题
1.组件之间复用状态逻辑很难
2.复杂组件变得难以理解
hook出现后保存的地方 每一个hook对应一个hook对象 这个对象上存着状态值 reducer值 这个hook对象又以单链表的数据结构存在Fiber存在内存
useReducer和useState
useState传入的是initiate state可以数值和函数 简单转态可以使用此 组件会更新 如一致也不更新
useReducer传入reducer纯函数 initiateArg初始化参数 initiate初始化函数 抽离修改逻辑 发生变化 组件会更新 如一致也更新
useState, useReducer返回一个数组解构方便 如果是对象还需要自己改名
useRef和useState useState是一个状态值而useRef是一个记录值比如ant-form4里面记录store或者ahooks中初始化定时器等等 虽然他们都是放在hook.memoizestate上
useEffect/useLayoutEffect useEffect组件渲染到屏幕后延迟执行 不会阻碍UI 和组件渲染不是一个task而uselayout和组件渲染是一个task 阻碍UI渲染 dom变更后同步执行 例如监听router
解释useImpreativeHandle
把ref暴露给父组件 暴露方法给父组件