React
未读Fiber架构的背景传统Stack Reconciler的局限性在Fiber架构之前,React使用Stack Reconciler(栈协调器),存在以下问题:
不可中断的渲染:一旦开始渲染,必须完成整个树的计算
阻塞主线程:大量计算会导致页面卡顿
优先级处理困难:无法区分高优先级和低优先级更新
Fiber架构的设计目标
可中断的工作:将渲染工作分解为小单元,可以暂停和恢复
优先级调度:根据不同优先级安排工作执行顺序
并发渲染:支持并发模式下的渲染
错误边界:更好的错误处理机制
Fiber节点的数据结构Fiber节点的核心属性1234567891011121314151617181920212223242526272829303132// Fiber节点的基本结构const fiberNode = { // 标识信息 tag: WorkTag, // 组件类型(函数组件、类组件等) key: null, // 唯一标识 type: null, // 组件类型或DOM标签名 // 状态信息 s ...
从本讲开始,我们将以首次渲染为切入点,拆解 Fiber 架构下 ReactDOM.render 所触发的渲染链路,结合源码理解整个链路中所涉及的初始化、render 和 commit 等过程
一、ReactDOM.render 调用栈的逻辑分层开篇先给到你一个简单的 React AppDemo:
1234567891011121314151617import React from "react";import ReactDOM from "react-dom";function App() { return ( <div className="App"> <div className="container"> <h1>我是标题</h1> <p>我是第一段话</p> <p>我是第二段话</p> </div> </ ...
current 树 与 workInProgress 树:”双缓存”模式在 Fiber 架构下的实现什么是”双缓存”模式“双缓存”模式其实是一种在游戏领域由来已久的经典设计模式。
为了帮助你快速理解它,这里我先举一个生活中的例子:假如你去看一场总时长只有 1 个小时的话剧,这场话剧中场不休息,需要不间断地演出。按照剧情的需求,半个小时处需要一次转场。所谓转场,就是说话剧舞台的灯光、布景、氛围等全部要切换到另一种风格里去。在不中断演出的情况下,想要实现转场,怎么办呢?场务工作做得再快,也要十几二十分钟,这对一场时长 1 小时的话剧来说,实在太漫长了。观众也无法接受这样的剧情”卡顿”体验。有一种解法,那就是准备两个舞台来做这场戏,当第一个舞台处于使用中时,第二个舞台的布局已经完成。这样当第一个舞台的表演结束时,只需要把第一个舞台的灯光灭掉,第二个舞台的灯光亮起,就可以做到剧情的无缝衔接了。事实上,在真实的话剧中,我们也确实常常看到这样的画面——演员从舞台的左侧走到了右侧,灯光一切换,就从卧室(左侧舞台)走到了公园(右侧舞台);又从公园(右侧舞台)走到了办公室(左侧舞台)。左侧舞台的布景从卧 ...
React Hooks 使用原则React 团队面向开发者给出了两条 React-Hooks 的使用原则,原则的内容如下:
只在 React 函数中调用 Hook;
不要在循环、条件或嵌套函数中调用 Hook。
从现象看问题:若不保证 Hooks 执行顺序,会带来什么麻烦先来看一个小 Demo:
123456789101112131415161718192021222324252627282930313233343536import React, { useState } from "react";function PersonalInfoComponent() { // 集中定义变量 let name, age, career, setName, setCareer; // 获取姓名状态 [name, setName] = useState("修言"); // 获取年龄状态 [age] = useState("99"); // 获取职业状态 [career, setCaree ...
React
未读何谓类组件(Class Component)所谓类组件,就是基于 ES6 Class 这种写法,通过继承 React.Component 得来的 React 组件。以下是一个典型的类组件:
123456789101112131415161718192021222324252627class DemoClass extends React.Component { // 初始化类组件的 state state = { text: "" }; // 编写生命周期方法 didMount componentDidMount() { // 省略业务逻辑 } // 编写自定义的实例方法 changeText = (newText) => { // 更新 state this.setState({ text: newText }); }; // 编写生命周期方法 render render() { return ...
requestIdleCallback它提供了一种机制,允许开发者在浏览器空闲时运行低优先级的任务,而不会影响关键任务和动画的性能。requestIdleCallback 执行阶段
浏览器一针里面做的任务
处理事件的回调: 用户的点击 input
处理计时器的回调,event loop
开始渲染 begin帧
执行requestAnimationFrame 动画回调
计算机页面布局计算 合并到主线程
绘制 回流和重绘
如果此时还有空闲时间,执行requestIdleCallback (这个是有条件的!)
requestIdleCallback 基本用法requestIdleCallback 接受一个回调函数 callback 并且在回调函数中会注入参数 deadline
deadline有两个值:● deadline.timeRemaining() 返回是否还有空闲时间(毫秒)● deadline.didTimeout 返回是否因为超时被强制执行(布尔值)
options:● { timeout: 1000 } 指定回调的最大等待时间(以毫秒为单位)。如果在指定的 timeou ...
React
未读一、React Router基础之history1.1 History介绍history是一个独立的第三方js库,可以用来兼容在不同浏览器、不同环境下对历史记录的管理,拥有统一的API。具体来说里面的history分为三类
老浏览器的history: 主要通过hash来实现,对应createHashHistory
高版本浏览器: 通过html5里面的history,对应createBrowserHistory
node环境下: 主要存储在memeory里面,对应createMemoryHistory
上面针对不同的环境提供了三个API,但是三个API有一些共性的操作,将其抽象了一个公共的文件createHistory
123456789101112131415161718// 内部的抽象实现function createHistory(options={}) { ... return { listenBefore, // 内部的hook机制,可以在location发生变化前执行某些行为,AOP的实现 listen, // ...
React
未读从Stack Reconciler到Fiber Reconciler在React 16.x版本中,React团队将其最为核心的Diff算法整个重写,使其以”Fiber Reconciler”的全新面貌示人。
那么Stack Reconciler到底有着怎样根深蒂固的局限性,使得React不得不从架构层面做出改变?而Fiber架构又是何方神圣,基于它来实现的调和过程又有什么不同呢?
前置知识:单线程的JavaScript与多线程的浏览器大家在入门前端的时候,想必都听说过这样一个结论:JavaScript是单线程的,浏览器是多线程的。
对于多线程的浏览器来说,它除了要处理JavaScript线程以外,还需要处理包括事件系统、定时器/延时器、网络请求等各种各样的任务线程,这其中,自然也包括负责处理DOM的UI渲染线程。而JavaScript线程是可以操作DOM的。
这意味着什么呢?试想如果渲染线程和JavaScript线程同时在工作,那么渲染结果必然是难以预测的:比如渲染线程刚绘制好的画面,可能转头就会被一段JavaScript给改得面目全非。这就决定了JavaScript线程和渲 ...
快速搞定虚拟 DOM 的两个”大问题”虚拟 DOM(Virtual DOM)本质上是JS 和 DOM 之间的一个映射缓存,它在形态上表现为一个能够描述 DOM 结构及其属性信息的 JS 对象
就这个示例来说,你需要把握住以下两点:
虚拟 DOM 是 JS 对象
虚拟 DOM 是对真实 DOM 的描述
我们看看 React 中的虚拟 DOM 大致是如何工作的
挂载阶段,React 将结合 JSX 的描述,构建出虚拟 DOM 树,然后通过 ReactDOM.render 实现虚拟 DOM 到真实 DOM 的映射(触发渲染流水线);
更新阶段,页面的变化在作用于真实 DOM 之前,会先作用于虚拟 DOM,虚拟 DOM 将在 JS 层借助算法先对比出具体有哪些真实 DOM 需要被改变,然后再将这些改变作用于真实 DOM。
虚拟 DOM 是如何解决问题的
而在虚拟 DOM 的加持下,事情变成了这样:
注意图中的”模板”二字加了引号,这是因为虚拟 DOM 在实现上并不总是借助模板。比如 React 就使用了 JSX,前面咱们着重讲过,JSX 本质不是模板,而是一种使用体验和模板相似的 JS ...
什么是Tapable?简单来说,Tapable 就是一个轻量级的插件架构框架。它提供了一套灵活的”钩子”(Hook)系统,让应用程序可以通过插件来扩展功能。
你可以把它想象成一个 “Event Bus 事件总线” 的升级版,但比普通的事件系统要强大得多。它 不仅能发布和订阅事件,还能 控制事件的执行顺序、处理异步操作、实现熔断机制 等等。
12345678910111213141516171819202122232425// 最简单的Tapable使用示例const { SyncHook } = require('tapable');class Car { constructor() { this.hooks = { accelerate: new SyncHook(['newSpeed']), brake: new SyncHook() }; } setSpeed(newSpeed) { // 触发钩子 this.h ...











