react 源码解析 5.jsx& 核心 api
react 源码解析 5.jsx&核心 api
视频课程(高效学习):进入课程
课程目录:
virtual Dom 是什么
一句话概括就是,用 js 对象表示 dom 信息和结构,更新时重新渲染更新后的对象对应的 dom,这个对象就是 React.createElement()的返回结果
virtual Dom 是一种编程方式,它以对象的形式保存在内存中,它描述了我们 dom 的必要信息,并且用类似 react-dom 等模块与真实 dom 同步,这一过程也叫协调(reconciler),这种方式可以声明式的渲染相应的 ui 状态,让我们从 dom 操作中解放出来,在 react 中是以 fiber 树的形式存放组件树的相关信息,在更新时可以增量渲染相关 dom,所以 fiber 也是 virtual Dom 实现的一部分
为什么要用 virtual Dom
大量的 dom 操作慢,很小的更新都有可能引起页面的重新排列,js 对象优于在内存中,处理起来更快,可以通过 diff 算法比较新老 virtual Dom 的差异,并且批量、异步、最小化的执行 dom 的变更,以提高性能
另外就是可以跨平台,jsx --> ReactElement 对象 --> 真实节点,有中间层的存在,就可以在操作真实节点之前进行对应的处理,处理的结果反映到真实节点上,这个真实节点可以是浏览器环境,也可以是 Native 环境
virtual Dom 真的快吗?其实 virtual Dom 只是在更新的时候快,在应用初始的时候不一定快
jsx&createElement
jsx 可以声明式的描述视图,提升开发效率,通过 babel 可以转换成 React.createElement()的语法糖,也是 js 语法的扩展。
jsx 是 ClassComponent 的 render 函数或者 FunctionComponent 的返回值,可以用来表示组件的内容,在经过 babel 编译之后,最后会被编译成React.createElement
,这就是为什么 jsx 文件要声明import React from 'react'
的原因(react17 之后不用导入),你可以在 <a name="https://www.babeljs.cn/repl">babel 编译 jsx</a> 站点查看 jsx 被编译后的结果
React.createElement
的源码中做了如下几件事
处理 config,把除了保留属性外的其他 config 赋值给 props
把 children 处理后赋值给 props.children
处理 defaultProps
调用 ReactElement 返回一个 jsx 对象(virtual-dom)
这里的 typeof 表示的是组件的类型,例如在源码中有一个检查是否是合法 Element 的函数,就是根 object.$$typeof === REACT_ELEMENT_TYPE 来判断的
如果组件是 ClassComponent 则 type 是 class 本身,如果组件是 FunctionComponent 创建的,则 type 是这个 function,源码中用 ClassComponent.prototype.isReactComponent 来区别二者。注意 class 或者 function 创建的组件一定要首字母大写,不然后被当成普通节点,type 就是字符串。
jsx 对象上没有优先级、状态、effectTag 等标记,这些标记在 Fiber 对象上,在 mount 时 Fiber 根据 jsx 对象来构建,在 update 时根据最新状态的 jsx 和 current Fiber 对比,形成新的 workInProgress Fiber,最后 workInProgress Fiber 切换成 current Fiber。
render
可以看到 render 所做的事也就是调用 legacyRenderSubtreeIntoContainer,这个函数在下一章讲解,这里重点关注 ReactDom.render()使用时候的三个参数。
component
component 函数中主要在当前实例上挂载了 props、context、refs、updater 等,所以在组件的实例上能拿到这些,而更新主要的承载结构就是 updater, 主要关注 isReactComponent,它用来表示这个组件是类组件
总结:jsx 是 React.createElement 的语法糖,jsx 通过 babel 转化成 React.createElement 函数,React.createElement 执行之后返回 jsx 对象,也叫 virtual-dom,Fiber 会根据 jsx 对象和 current Fiber 进行对比形成 workInProgress Fiber
pureComponent 也很简单,和 component 差不多,他会进行原型继承,然后赋值 isPureReactComponent
版权声明: 本文为 InfoQ 作者【全栈潇晨】的原创文章。
原文链接:【http://xie.infoq.cn/article/72a941b9eed8c51632c832c6a】。文章转载请联系作者。
评论