导语
React 中的 key 真实的工作原理是怎么样的。
简易开发脚手架
快速开启一个全新的项目,选用 rollup 尝鲜。不使用 create-react-app ,是因为其内置了 React ,导致解析时无法使用我们自己的 React 版本。
- 添加 @babel/preset-react ,帮助我们解析转换 jsx 语法
- 注意 config 中 Babel 的添加顺序,保证先转换语法后再进行其他操作
- 添加 prettier,自动格式化
Babel
React 中引入 Jsx
的语法来编写 html 和 js ,这种混合的写法 js 引擎并不认识,所以需要 Babel 来转译 Jsx。同理我们可以使用先进的 es6+
的语法,依托 Babel 转译为低版本浏览器可以识别的 es5 语法。
[Jsx 转译](babeljs.io/repl#?brows…](babeljs.io/repl#?brows…)
ReactElement
React 帮助我们屏蔽了底层的各种 dom 操作,使得我们可以专心操作 UI 组件,核心是 virtual dom 的概念,用一个简单的对象来表示一个 dom 节点,这个对象具体的实现就是一个 reactElement , 我们在使用的过程中常用的dom 组件、函数式组件、类组件等,都会被创建成对应类型的 reactElement 。
React.createElement=function(type,config,children){
///
return {
$$typeof,
type,
props,
key,
ref,
}
}
ReactDom.render
负责首次渲染,核心逻辑3条:
- 根据传入的
element
的type
不同,分别生成不同的操作实例。 - 调用生成实例的
mountComponent
方法,生成真实的dom
。 - 将真实的
dom
挂载到传入的container
上面。
操作类,用来管理具体的 dom
节点的挂载、更新、卸载操作。通用的结构如下:
class ReactXXXComponent {
constructor(element){
this._currentElement = element;
this._hostNode = null;
}
// 挂载
mountComponent(){
let dom = null;
this._hostNode = null;
return dom = null;
}
// 更新
updateComponent(){}
// 卸载
unmountComponent(){
this._currentElement = null;
this._hostNode = null;
}
}
首次挂载后,将生成的真实dom
保存在 _hostNode
上。
React 实例关系图
核心是 React Element,React 获取到 React Element 后,生成不同的操作实例。
实际应用中,主要应用的是 ReactCompositeComponent 组件。很少会直接用到一段纯 UI 的 ReactDomComponent,通常都会在 ReactDomComponent 的基础上添加自有的 state。