前端面试资料整理【React篇】

React
参考
React 源码 react 为什么实用 JSX?
萝卜青菜各有所爱。
但是 react 团队认为模板方案不好:

  • 模板分离了技术栈,增加了技术点。
  • 看起来像 html 的 jsx。
  • react 规矩性太强,需要 jsx 来辅助
例如使用 vue 上面是 html 模板,下面是js逻辑从而形成一个组件功能。但是 react 将 html 和运行逻辑都运行在一个 class。
JSX 映射虚拟 DOM 的原理?
JSX 是 creatElement 的语法糖,使用的是 babel 的转义器,实际是通过两个方法完成,一个是 creatElement,一个 reactElement
// 定义一个 react 对象 reactElement(type, key, ref, self, source, ReactCurrentOwner.current, props)

Rreact 数据流管理
数据驱动视图?
UI = render(data)
data 与 state 的区别是什么?
状态(state)与数据(data),组件中的通信就是 data 的通信,react 核心就是对数据的管理
数据流动:
  • 父 -> 子
  • 子 -> 父
  • 兄弟
  • 无关系
单向数据流
MVC的劣势双向数据流。引起混乱。
Action -> Dispatcher -> Store -> View
|-------<------Action<-|

ACTION 视图层发送的消息
redux 是 js 的状态容器
Action -> Reducer -> Store[state, state]
|-------<------View--<-|

redux 优缺点
缺点:
  • 使用流程复杂。
  • state 不会随着组件销毁,状态残留。
  • 频繁更新 store 时,会更加卡顿。
  • 不支持 ts。
mobx
原理是利用 es6 proxy 数据劫持,不会想 redux 使用复杂。
React Fiber 超过 16 毫秒后会掉帧。
原来的 React 是通过利用js的执行栈,一直执行到栈空位置。新版的React 维护了自己的执行栈,通过链表的形式,遍历树形结构,优化了执行过程。
参考
虚拟 DOM 和 diff算法 虚拟 DOM
React 渲染 dom 的一种优化手段,其原理是利用 createFragment ,即“创造碎片”。所有的 DOM 操作都将在“碎片”中操作,直到操作完成,再一起渲染。
diff 算法
是 React 更新 dom 元素的一套算法,其核心思想是,比较“节点树”的各个节点,根据比较的结果来决定是否更新该节点。通过其优化手段,将更新树的时间复杂度从O(n^3)变为O(n)。
diff 策略
  • 忽略跨组件的移动操作
  • 同类组件创建相同树,不同类则创建不同类的数(React Component 和 function Component)
  • 兄弟,key
分为3个更新策略 tree diff, component diff, element diff:
tree diff: 当遇到树形结构更新时,仅比较同层节点,起子节点仅有创建和删除。这就意味这,如果存在移动某个树形结构的中间节点,那么原树将直接删除该节点及其子节点,在新树中创建起节点及其子节点。另外,官方不建议存在跨节点的移动操作。
component diff: 当节点更新为不同类型的节点时,成为 dirty component,react 认为更新成不同类型的节点,其结构一定是不一样的(树形结构),因此直接删除该节点后,直接创建。
element diff: 计算兄弟节点直接的移动操作,由原来的将目标位节点删除再创建的更新策略,更改为通过标识key,判断是为原来的节点,另外也获得了是否产生移动操作的判断依据。
由此也得出了3条优化建议:
  • 设置 key
  • 不要将组件更新为不同类型
  • 减少将兄弟组件从末尾移至头部的操作
参考
Redux 待补充
React 优化 常见的优化细节:
  • function 组件代替 class 组件 -> 为什么?参考1 参考2
  • HOC
  • 使用 redux 这类状态管理工具时,部分不公用的state 不用挂载在 model 中 --> 为什么?
  • 首屏优化方案
  • lazy 懒加载组件
  • react-router 的 loading 改善体验
  • ssr (service side rendering)和 csr (client side rendering)
  • pureComponent 和 shouldUpdate 优化更新频率
  • componentDidCatch 探测错误边界
  • 通过 Fragment 减少标签深度
  • render 函数中的变量声明提升到外面,减少 GC
React-Hooks useState 相当于 class component 中的 setState。
function render() { ReactDom.render(, document.getElementById('root')) } function myState(initState) { let state = initState const update = (newState) => { state = newState render()} return [state, update] } function App () {}

useEffect 相当于 class component 中的若干声明周期函数
为什么16.8加入Hook?或者为什么增加 function component?
  • class component 复用状态会很难。HOC 虽然解决了,但是有嵌套地狱的问题。
  • class component 声明周期如果存在更改,其他生命周期可能均需要更改。
  • es6 的 class 不如 function 对初学者更友好
  • this 的指向
官方回答
站在设计者的角度来思考。
SSR next 主要是用在 React。
npx create-next-app

react-router 根据 history 开发的无刷新路由器。
主要有3个类型:hashHistory、borwerHistory、memoryHistory,常用的是 hashHistory 和 browerHistory。
新版本是 react-router-dom,
import React from "react"; import { Router } from "react-router"; import { createBrowserHistory as createHistory } from "history"; import PropTypes from "prop-types"; import warning from "tiny-warning"; /** * The public API for a that uses HTML5 history. */ class BrowserRouter extends React.Component { history = createHistory(this.props); render() { return ; } }export default BrowserRouter;

区别

browerHistory 与 hashHistory 区别 hash 路由是是根据改变 # 后面的锚点来刷新,通过 window.onhashChange 监听变化,从而根据路由处找到相应的文件
history 是通过 html5 的 window.history 这个 web API 来实现
hashHistory的特点:
  • 使用的是 history.location.hash 即 history.location.hash = "abc" (相当于是 localhost/#abc)
  • 只能通过修改 # 后面的地址实现刷新
  • 通过 window.onhashchange 监听 hash 变化,window.addEventListener('onhashchange', hashchangeHandler)
  • 不能想 window.history.go(-1) 这种方式,只能通过字符串改变 url
  • 对搜索引擎不友好,且不好追踪
browerHistory的特点:
  • 使用的是 History 对象,提供 go, back, forward 的方法
  • 相同的 url 会发生更新,并且压入历史记录中
  • 通过 push 和 replace 方法,实际是通过 pushState,replaceState 实现无刷新跳转。其中 pushState 会压入浏览器历史栈,即 History.length + 1,replaceState 则不会。
问题
使用 history 更新路由且正常渲染后,再刷新,会引起404。(待验证)
是由于 history 更新了 url,也就是访问地址,此时向后端服务器请求时,如果没有匹配地址的资源则会 404。
例如 nginx 配置 /test 地址访问。通过 history router 从 /test 跳转至 /say ,刷新时,服务器将找不到资源,可以通过配置父级路径规避掉。
【前端面试资料整理【React篇】】window.location 也会更改 url 但是会引起刷新

    推荐阅读