react源码解析20.总结&第一章的面试题解答

react源码解析20.总结&第一章的面试题解答

视频课程(高效学习):进入课程

课程目录:

1.开篇介绍和面试题

2.react的设计理念

3.react源码架构

4.源码目录结构和调试

5.jsx&核心api

6.legacy和concurrent模式入口函数

7.Fiber架构

8.render阶段

9.diff算法

10.commit阶段

11.生命周期

12.状态更新流程

13.hooks源码

14.手写hooks

15.scheduler&Lane

16.concurrent模式

17.context

18事件系统

19.手写迷你版react

20.总结&第一章的面试题解答

21.demo

总结

至此我们介绍了react的理念,如果解决cpu和io的瓶颈,关键是实现异步可中断的更新

我们介绍了react源码架构(ui=fn(state)),从scheduler开始调度(根据过期事件判断优先级),经过render阶段的深度优先遍历形成effectList(中间会执行reconcile|diff),交给commit处理真实节点(中间穿插生命周期和部分hooks),而这些调度的过程都离不开Fiber的支撑,Fiber是工作单元,也是节点优先级、更新UpdateQueue、节点信息的载体,Fiber双缓存则提供了对比前后节点更新的基础。我们还介绍了jsx是React.createElement的语法糖。Lane模型则提供了更细粒度的优先级对比和计算,这一切都为concurrent mode提供了基础,在这之上变可以实现Suspense和batchedUpdate(16、17版本实现的逻辑不一样),18章context的valueStack和valueCursor在整个架构中运行机制,19章介绍了新版事件系统,包括事件生产、监听和触发

面试题简答(详见视频源码角度讲解)

  1. jsx和Fiber有什么关系

    答:mount时通过jsx对象(调用createElement的结果)调用createFiberFromElement生成Fiber
    update时通过reconcileChildFibers或reconcileChildrenArray对比新jsx和老的Fiber(current Fiber)生成新的wip Fiber树

  2. react17之前jsx文件为什么要声明import React from 'react',之后为什么不需要了

    答:jsx经过编译之后编程React.createElement,不引入React就会报错,react17改变了编译方式,变成了jsx.createElement

    function App() {
      return <h1>Hello World</h1>;
    }
    //转换后
    import {jsx as _jsx} from 'react/jsx-runtime';
    
    function App() {
      return _jsx('h1', { children: 'Hello world' });
    }
    
  1. Fiber是什么,它为什么能提高性能

    答:Fiber是一个js对象,能承载节点信息、优先级、updateQueue,同时它还是一个工作单元。

    1. Fiber双缓存可以在构建好wip Fiber树之后切换成current Fiber,内存中直接一次性切换,提高了性能
    2. Fiber的存在使异步可中断的更新成为了可能,作为工作单元,可以在时间片内执行工作,没时间了交还执行权给浏览器,下次时间片继续执行之前暂停之后返回的Fiber
    3. Fiber可以在reconcile的时候进行相应的diff更新,让最后的更新应用在真实节点上

hooks

  1. 为什么hooks不能写在条件判断中

    答:hook会按顺序存储在链表中,如果写在条件判断中,就没法保持链表的顺序

状态/生命周期

  1. setState是同步的还是异步的

    答:legacy模式下:命中batchedUpdates时是异步 未命中batchedUpdates时是同步的

    concurrent模式下:都是异步的

  2. componentWillMount、componentWillMount、componentWillUpdate为什么标记UNSAFE

    答:新的Fiber架构能在scheduler的调度下实现暂停继续,排列优先级,Lane模型能使Fiber节点具有优先级,在高优先级的任务打断低优先级的任务时,低优先级的更新可能会被跳过,所有以上生命周期可能会被执行多次,和之前版本的行为不一致。

组件

  1. react元素$$typeof属性什么

    答:用来表示元素的类型,是一个symbol类型

  2. react怎么区分Class组件和Function组件

    答:Class组件prototype上有isReactComponent属性

  3. 函数组件和类组件的相同点和不同点

    答:相同点:都可以接收props返回react元素

    不同点:

    编程思想:类组件需要创建实例,面向对象,函数组件不需要创建实例,接收输入,返回输出,函数式编程

    内存占用:类组建需要创建并保存实例,占用一定的内存

    值捕获特性:函数组件具有值捕获的特性 下面的函数组件换成类组件打印的num一样吗

    export default function App() {
      const [num, setNum] = useState(0);
      const click = () => {
        setTimeout(() => {
          console.log(num);
        }, 3000);
        setNum(num + 1);
      };
    
      return <div onClick={click}>click {num}</div>;
    }
    
    
    export default class App extends React.Component {
      state = {
        num: 0
      };
    
      click = () => {
        setTimeout(() => {
          console.log(this.state.num);
        }, 3000);
        this.setState({ num: this.state.num + 1 });
      };
    
      render() {
        return <div onClick={this.click}>click {this.state.num}</div>;
      }
    }
    
    
    

可测试性:函数组件方便测试

状态:类组件有自己的状态,函数组件没有只能通过useState

生命周期:类组件有完整生命周期,函数组件没有可以使用useEffect实现类似的生命周期

逻辑复用:类组件继承 Hoc(逻辑混乱 嵌套),组合优于继承,函数组件hook逻辑复用

跳过更新:shouldComponentUpdate PureComponent,React.memo

发展未来:函数组件将成为主流,屏蔽this、规范、复用,适合时间分片和渲染

开放性问题

  1. 说说你对react的理解/请说一下react的渲染过程

    答:是什么:react是构建用户界面的js库

    能干什么:可以用组件化的方式构建快速响应的web应用程序

    如何干:声明式(jsx) 组件化(方便拆分和复用 高内聚 低耦合) 一次学习随处编写

    做的怎么样: 优缺(社区繁荣 一次学习随处编写 api简介)缺点(没有系统解决方案 选型成本高 过于灵活)

    设计理念:跨平台(虚拟dom) 快速响应(异步可中断 增量更新)

    性能瓶颈:cpu io fiber时间片 concurrent mode

    渲染过程:scheduler render commit Fiber架构

  2. 聊聊react生命周期
    详见第11章

  3. 简述diff算法
    详见第9章

  4. react有哪些优化手段

    答:shouldComponentUpdate、不可变数据结构、列表key、pureComponent、react.memo、useEffect依赖项、useCallback、useMemo、bailoutOnAlreadyFinishedWork ...

  5. react为什么引入jsx

    答:jsx声明式 虚拟dom跨平台

    解释概念:jsx是js语法的扩展 可以很好的描述ui jsx是React.createElement的语法糖

    想实现什么目的:声明式 代码结构简洁 可读性强 结构样式和事件可以实现高内聚 低耦合 、复用和组合 不需要引入新的概念和语法 只写js, 虚拟dom跨平

    有哪些可选方案:模版语法 vue ag引入了控制器 作用域 服务等概念

    jsx原理:babel抽象语法树 classic是老的转换 automatic新的转换

  6. 说说virtual Dom的理解

    答:是什么:React.createElement函数返回的就是虚拟dom,用js对象描述真实dom的js对象

    优点:处理了浏览器的兼容性 防范xss攻击 跨平台 差异化更新 减少更新的dom操作

    缺点:额外的内存 初次渲染不一定快

  7. 你对合成事件的理解

    类型 原生事件 合成事件
    命名方式 全小写 小驼峰
    事件处理函数 字符串 函数对象
    阻止默认行为 返回false event.preventDefault()

    理解:

    • React把事件委托到document上(v17是container节点上)
    • 先处理原生事件 冒泡到document上在处理react事件
    • React事件绑定发生在reconcile阶段 会在原生事件绑定前执行

    优势:

    • 进行了浏览器兼容。顶层事件代理,能保证冒泡一致性(混合使用会出现混乱)
    • 默认批量更新
    • 避免事件对象频繁创建和回收,react引入事件池,在事件池中获取和释放对象(react17中废弃)
      react17事件绑定在容器上了
  1. 我们写的事件是绑定在dom上么,如果不是绑定在哪里?
    答:v16绑定在document上,v17绑定在container上
  2. 为什么我们的事件手动绑定this(不是箭头函数的情况)
    答:合成事件监听函数在执行的时候会丢失上下文
  3. 为什么不能用 return false来阻止事件的默认行为?
    答:说到底还是合成事件和原生事件触发时机不一样
  4. react怎么通过dom元素,找到与之对应的 fiber对象的?
    答:通过internalInstanceKey对应
    react源码18.2

解释结果和现象

  1. 点击Father组件的div,Child会打印Child吗

    function Child() {
      console.log('Child');
      return <div>Child</div>;
    }
    
    
    function Father(props) {
      const [num, setNum] = React.useState(0);
      return (
        <div onClick={() => {setNum(num + 1)}}>
          {num}
          {props.children}
        </div>
      );
    }
    
    
    function App() {
      return (
        <Father>
          <Child/>
        </Father>
      );
    }
    
    const rootEl = document.querySelector("#root");
    ReactDOM.render(<App/>, rootEl);
    
答: 不会,源码中是否命中bailoutOnAlreadyFinishedWork
  1. 打印顺序是什么

    function Child() {
      useEffect(() => {
        console.log('Child');
      }, [])
      return <h1>child</h1>;
    }
    
    function Father() {
      useEffect(() => {
        console.log('Father');
      }, [])
      
      return <Child/>;
    }
    
    function App() {
      useEffect(() => {
        console.log('App');
      }, [])
    
      return <Father/>;
    }
    
答:Child ,Father ,App ,render阶段mount时深度优先遍历,commit阶段useEffect执行时机
  1. useLayout/componentDidMount和useEffect的区别是什么

    class App extends React.Component {
      componentDidMount() {
        console.log('mount');
      }
    }
    
    useEffect(() => {
      console.log('useEffect');
    }, [])
    
答:他们在commit阶段不同时机执行,useEffect在commit阶段结尾异步调用,useLayout/componentDidMount同步调用

![react源码20.1](https://upload-images.jianshu.io/upload_images/25882458-4dc6ac1da89812b9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  1. 如何解释demo_4、demo_8、demo_9出现的现象

    答:demo_4:useEffect和useLayoutEffect的区别
    demo_8:任务的优先级有关,见源码分析视频
    demo_9:批量更新有关,见源码分析视频

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容