前言
通过学习冴羽老师的react源码文章,写一篇自己理解的读后感。
文章会通过一些问答的形式,帮助大家更快的记住一些知识点。
什么是babel
在react中,采用jsx语法,通过babel进行转换,转换成浏览器可以执行的js代码。
babel是一个javascript的编译器,可以将JSX编译成javascript函数
babel将jsx转换成什么
babel最终会将jsx代码,转换成React.createElement()函数。
<div id="foo">bar</div>
// babel编译后
React.createElement("div", {id: "foo"}, "bar");
createElement()函数参数
createElement(type, config, children)接受三个参数
第一个参数是元素类型,第二个参数是元素属性,第三个参数是子元素。
createElement源码解析
学习前可先下载React源码,和这篇文章一起学习。
git仓库地址:github.com/facebook/re…
- 查看
packages/react/index.js文件
export {createElement} from './src/React'
- 进入
./src/React文件
import {createElementWithValidation} from './ReactElementValidator'
import {createElement as createElementProd} from './ReactElement';
const createElement = __DEV__ ? createElementWithValidation : createElementProd;
export {createElement}
- 进入
ReactElement文件 (重点)
const RESERVED_PROPS = {
key: true,
ref: true,
__self: true,
__source: true,
};
export function createElement(type, config, children) {
let propName;
// Reserved names are extracted
const props = {};
// 第一步逻辑:将一些判断条件省略,更方便阅读源码
let key = '' + config.key;
let ref = config.ref;
let self = config.__self;
let source = config.__source;
// 第二步逻辑:构建props对象,去除传入的key、ref、__self、__source
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName];
}
}
// 第三步逻辑:将children参数进行处理。children可能有多个参数
// 当children只有一个元素时,它是一个Object。当children有多个子元素时,它是是一个对象数组
props.children = children;
// 第四步逻辑:对type处理,处理组件的defaultProps
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
// 第五步 将处理好的数据传入ReactElement函数
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
}
createElement作用?
createElement主要做一个预处理的作用,处理传入的参数,将处理好的数据传入ReactElement函数- 为什么通过
props获取不到key,ref
在ceateElement()函数中,对props参数进行处理,去除传入的key、ref、__self、__source属性,这就是为什么在组件中,我们明明传入了key和ref,但我们无法通过this.props.key或者this.props.ref来获取传入的值,就是因为在这里被去除掉了。如果需要用到key,给他一个其他属性,还传递key值。 - 什么是
defaultProps?
在函数组件或者类组件中,都可以设置defaultProps
// 类组件
class Demo extends Components{
static defaultPoprs = { name: 'lily' }
}
// 函数组件
function Demo(id){
return <div id={id}>函数组件</div>
}
Demo.defaultProps={ id : 'lili'}
- 进入
ReactElement()函数
返回一个React元素,React会通过读取这些对象,使用它们构建和更新DOM
import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// This tag allows us to uniquely identify this as a React Element防止受xss攻击
// react元素的节点类型
$$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element
type: type,
key: key,
ref: ref,
props: props,
// Record the component responsible for creating this element.
_owner: owner,
};
return element
}
参考文章: juejin.cn/post/716098…