React常见面试题——原理篇

函数式编程

  • 函数式编程是一种编程范式, 对过程进行抽象,将数据以输入输出流的方式封装进过程内部, 从而也降低系统的耦合度。
  • 纯函数:即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用, 副作用包括但不限于:
    • 打印/log
    • 发送一个http请求
    • DOM查询
    • 可变数据
    • 简单一句话, 即只要是与函数外部环境发生交互的都是副作用。
    • 像js中的slice是纯函数,splice则不是纯函数

vdom和diff

  • 对于 vdom 和 diff,h 函数、vdom 数据结构、patch 函数。只比较同一层级,不跨级比较。tag 不相同,则直接删掉重建,不再深度比较。tag 和 key,两者都相同,则认为是相同节点,不再深度比较
    简述diff算法过程.

jsx本质

  • JSX的本质即React.createElement函数,React.createElement 即 h 函数,返回vnode
  • React.createElement的第一个参数是渲染的标签,第二个参数为标签的属性,之后的为子元素
    • 第一个参数,可能是组件,也可能是一个html tag(组件和tag区分是大小写,组件名首字母必须要大写)
  • 函数返回值是一个vnode
  • vnode在通过patch函数进行渲染
// 如下是一个循环的编译
const listElem = <ul>
        {this.state.list.map((item, inedx) => {
          return (<li key={item.id}>
            index: {index}; title:{item.titlle}
          </li>)
        })}
</ul>

// 编译结果如下:
var listElem = /*#__PURE__*/React.createElement("ul", null, (void 0).state.list.map(function (item, inedx) {
  return /*#__PURE__*/React.createElement("li", {
    key: item.id
  }, "index: ", index, "; title:", item.titlle);
}));

合成事件

  • 所有的事件都挂在到document
  • event不是原生的,是SyntheticEvent合成事件对象
  • 和Vue事件不同,和DOM事件也不同
    在这里插入图片描述
  • DOM事件会冒泡到document上,document会生成一个统一的React event,在合成事件层会派发事件(通过target可以获取到哪个元素触发的事件,找到这个元素所在组件这个)
  • 为什么要合成事件机制
    • 更好的兼容性和跨平台
    • 挂在到document,减少内存消耗,避免频繁解绑
    • 方便事件的统一管理(如事物机制)

setState和batchUpdate

  • setState有时异步(普通使用),有时同步(setTimeout, 自己定义的DOM事件)

  • 有时合并(对象形式), 有时不合并(函数形式)

  • 调用了setState之后,newState会被存入pending队列

  • 是否处于batch update机制中

    • 处于batch update机制中, 保存组件与dirtyComponent(state被更新的component)中(走异步操作)
    • 不处于batch update机制中,遍历所有的dirtyComponent,调用updateCompoennt,更新pending state or props(走同步操作)
  • 如何判断是否处于batch update中,是需要根据isBatchingUpdates进行判断

  • 因此:setState无所谓同步和异步,需要看是否命中batchUpdate机制,是否命中batchUpdate机制的判断就是isBatchingUpdate

increase(){
   // 开始:处于batch update
   // isBatchingUpdate = true
   this.setState({
     count: this.state.count+1
   })
   // 结束
   // // isBatchingUpdate = false
 }
  
 // 在increase1中,当执行到setState时,isBatchingUpdate 已经为false
 increase1(){
   // 开始:处于batch update
   // isBatchingUpdate = true
   setTimeout(() => {
     this.setState({
       count: this.state.count+1
     })
   }, 0)
   // 结束
   // // isBatchingUpdate = false
 }
  
componentDidMount(){
    // 开始:处于batch update
    // isBatchingUpdate = true
    document.body.addEventListener('click', () => {
      this.setState({
        count: this.state.count+1
      })
      console.log('count in body event', this.state.count);
    })
    // 结束
    // // isBatchingUpdate = false
  }
  • 那些能命中batchUpdate机制?
    • 生命周期(和它调用的函数)
    • React中注册的事件(和它调用的函数)
    • React可以 “管理” 的入口
  • 哪些不能够命中 batchUpdate 机制
    • setTimeout、setInterval 等和它调用的函数
    • 自定义的 DOM 事件和它调用的函数
    • React 管不到的入口

transaction事务机制

  • 对于 transition事务机制,开始处于 batchUpdateisBatchUpdates = true,其它任何操作,结束,isBatchUpdates = false
increase(){
   // 开始:处于batch update
   // isBatchingUpdate = true
   
   // 其它任何操作
   
   // 结束
   // // isBatchingUpdate = false
 }

组件渲染和更新过程

  • 渲染过程
    • 有了propsstate
    • render()生成vnode
    • patch(elem, vnode)
  • 更新过程
    • setState()—> dirtyComponents(可能有子组件)
    • 执行render函数,根据新的stateprops生成newVnode
    • patch(vnode, newVnode)
  • patch 更新的两个阶段
    • reconciliation阶段——执行diff算法,纯JS计算
    • commit阶段——将diff结果渲染DOM
  • 可能出现的性能问题(如果不将patch更新分为两个阶段的话可能出现的心梗问题)
    • JS 是单线程的,且和 DOM 渲染共用一个线程
    • 当组件足够复杂的时候,组件更新时计算和渲染都压力大
    • 同时再有 DOM 操作需求,如动画、鼠标拖拽等,将卡顿
  • fiber
    • reconciliation阶段进行任务拆分(但是 commit 无法拆分)
    • DOM 需要渲染时暂停更新,空闲时修复
    • 如何知道DOM需要渲染呢?是需要借助于window.requestIdleCallback
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React见面试题包括但不限于以下几个方面: 1. React组件的生命周期:React组件的生命周期分为三个阶段,分别是挂载阶段、更新阶段和卸载阶段。在每个阶段,都有相应的生命周期方法可以被调用,比如componentDidMount、componentDidUpdate和componentWillUnmount等。 2. React的虚拟DOM和DOM diff算法:React通过使用虚拟DOM来提高性能。虚拟DOM是一个轻量级的JavaScript对象,它表示真实DOM的层次结构。当数据发生变化时,React会使用DOM diff算法来比较新旧虚拟DOM树的差异,并只更新需要变化的部分,从而避免了对整个DOM树进行重渲染。 3. React中的状态管理:React有多种状态管理的方式,最用的是使用组件的state和props来管理状态。另外,还可以使用React的Context API、Redux、Mobx等来实现更灵活的状态管理。 4. React中的事件处理:在React中,可以通过给元素添加事件处理函数来处理用户的交互行为。见的事件处理方式包括直接在JSX中绑定事件处理函数、使用类组件中的成员方法作为事件处理函数、使用React的Hooks中的useEffect来处理副作用等。 5. React的组件通信:React组件之间的通信可以通过props传递数据、使用React的Context API、使用全局状态管理工具等方式实现。另外,如果组件之间的通信比较复杂,还可以考虑使用消息订阅-发布模式或者事件总线来实现。 6. React的性能优化:React提供了一些性能优化的手段,比如使用shouldComponentUpdate来控制组件的更新、使用React的memo和useMemo来缓存计算结果、使用React的Fragment来减少不必要的DOM节点等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值