一个有责任心的开发一定不会放任错误的发生。错误边界可以包在任何位置并提供降级 UI,也就是说,一旦开发者’有责任心’ 页面就不会全白,这也是我之前说的方案一与之天然冲突且其他方案不稳定的情况。那么,在这同时我们上报异常信息,这里上报的异常一定会导致我们定义的白屏,这一推导是 100% 正确的。
100% 这个词或许不够负责,接下来我们来看看为什么我说这一推导是 100% 准确的:
React 渲染流程
我们来简单回顾下从代码到展现页面上 React 做了什么。我大致将其分为几个阶段:render => 任务调度 => 任务循环 => 提交 => 展示 我们举一个简单的例子来展示其整个过程(任务调度不再本次讨论范围故不展示):
const App = ({ children }) => (
<>
hello
{ children }
</>
);
const Child = () =>
I’m child
const a = ReactDOM.render(
,
document.getElementById(‘root’)
);
准备
首先浏览器是不认识我们的 jsx 语法的,所以我们通过 babel 编译大概能得到下面的代码:
var App = function App(_ref2) {
var children = _ref2.children;
return React.createElement(“p”, null, “hello”), children);
};
var Child = function Child() {
return React.createElement(“p”, null, “I’m child”);
};
ReactDOM.render(React.createElement(App, null, React.createElement(Child, null)), document.getElementById(‘root’));
babel 插件将所有的 jsx 都转成了 createElement
方法,执行它会得到一个描述对象 ReactElement
大概长这样子:
{
$$typeof: Symbol(react.element),
key: null,
props: {}, // createElement 第二个参数 注意 children 也在这里,children 也会是一个 ReactElement 或 数组
type: ‘h1’ // createElement 的第一个参数,可能是原生的节点字符串,也可能是一个组件对象(Function、Class…)
}
所有的节点包括原生的 <a></a>
、 <p></p>
都会创建一个 FiberNode
,他的结构大概长这样:
FiberNode = {
elementType: null, // 传入 createElement 的第一个参数
key: null,
type: HostRoot, // 节点类型(根节点、函数组件、类组件等等)
return: null, // 父 FiberNode