看下babel编译结果javascript
首字母是不是大小写 判断翻译成字符串仍是变量组件的原理 html
源码文件目录 java
createElement有三个参数 type, config, children。 点击查看api 文档
实现的主要思路是: 点击进入下文代码 demo 在线编辑地址react
if (config != null) {
// 剔除config中的 key ref self source 属性 ,并赋予值
if (hasValidRef(config)) {
ref = config.ref;
}
if (hasValidKey(config)) {
key = "" + config.key;
}
self = config._self === undefined ? null : config._self;
source = config.__source === undefined ? null : config.__source;
// 将properties 添加到新的props对象中
// 使用hasOwnProperty.call 为防止 config对象自定义hasOwnProperty 属性
// 具体解释点击 https://www.jianshu.com/p/95839681776d
// 未知对象用 hasOwnProperty.call 已知对象能够直接使用 hasOwnProperty
for(propName in config){
if(
hasOwnProperty.call(config,propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
){
props[propName] = config[propName];
}
}
}
复制代码
// children 处理获得 props.children
const childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
const childrenArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childrenArray[i] = arguments[i + 2];
}
// freeze 冻结一个对象使其不可修改 且freeze为浅冻结
// mdn 地址 : https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
if (__DEV__) {
if (Object.freeze) {
Object.freeze(childrenArray);
}
}
props.children = childrenArray;
}
复制代码
// 若是是组件
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
复制代码
// __DEV__下warning 在displayName 组件中 key,ref 是不可配置的属性
if(__DEV__){
if(key || ref){
const displayName =
typeof type === 'function'
? type.displayName || type.name || 'Unknown'
: type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (ref) {
defineRefPropWarningGetter(props, displayName);
}
}
}
复制代码
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
复制代码
ReactElement 接收type, key, ref, self, source, owner, props 7各参数api
slef:
当React.createElement被调用时,用来检测this的来源,以便咱们能够发出警告。咱们想要摆脱全部者并用箭头函数替换字符串ref
s,只要this
和全部者是相同的就没有了改变行为 source:
一个注解对象 (由转路器或者其余人添加)。用来判断两个react element元素是否相等 owner:
记录负责建立此元素的组件数组
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// $$typeof是区分react Element对象的惟一标识
$$typeof: REACT_ELEMENT_TYPE,
// 属于元素的内置属性
type: type,
key: key,
ref: ref,
props: props,
// 记录负责建立此元素的组件.
_owner: owner,
};
if (__DEV__) {
element._store = {};
Object.defineProperty(element._store, 'validated', {
configurable: false,
enumerable: false,
writable: true,
value: false,
});
// self and source are DEV only properties.
Object.defineProperty(element, '_self', {
configurable: false,
enumerable: false,
writable: false,
value: self,
});
// 为了测试目的,在两个不一样的地方建立的两个元素应被视为相等,所以咱们将其隐藏在枚举中
Object.defineProperty(element, '_source', {
configurable: false,
enumerable: false,
writable: false,
value: source,
});
if (Object.freeze) {
Object.freeze(element.props);
Object.freeze(element);
}
}
return element;
};
复制代码
React Component 只是用来帮助咱们承载一些信息的,没有生命周期等功能的实现promise
function Component(props, context, updater) {
this.props = props;
this.context = context;
// If a component has string refs, we will assign a different object later.
this.refs = emptyObject;
// We initialize the default updater but the real one gets injected by the
// renderer.
this.updater = updater || ReactNoopUpdateQueue;
}
Component.prototype.isReactComponent = {};
复制代码
Componenet的prototype 挂载方法bash
PureComponent 进行的 浅比较 (shallow equality check)babel
function PureComponent(props, context, updater) {
this.props = props;
this.context = context;
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
}
const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
// Avoid an extra prototype jump for these methods.
Object.assign(pureComponentPrototype, Component.prototype);
// PureComponent 与 Component 本文件中代码上区别是
pureComponentPrototype.isPureReactComponent = true;
复制代码
三种使用ref的方式dom
import type {RefObject} from 'shared/ReactTypes';
// an immutable object with a single mutable value
export function createRef(): RefObject {
const refObject = {
current: null,
};
if (__DEV__) {
Object.seal(refObject);
}
return refObject;
}
复制代码
forwardRef 解决了 pure Function 没有ref实例的问题
forwardRef 返回 React$Node
官网api文档 Refs 转发
点击进入 : 在线代码demo编辑
点击进入 Suspense && lazy 使用demo 连接
import React, { Suspense } from "react";
import ReactDOM from "react-dom";
const LazyComp = React.lazy(() => import("./lazy"));
let data = "";
let promise = "";
const requestData = () => {
if (data) return data;
if (promise) throw promise;
promise = new Promise(res => {
setTimeout(() => {
data = "data res";
res();
}, 2000);
});
throw promise;
};
const SuspenseComp = () => {
const data = requestData();
return <div>{data}</div>;
};
const Comp = () => {
return (
<Suspense fallback="loading data"> <SuspenseComp /> <LazyComp /> </Suspense>
);
};
ReactDOM.render(<Comp />, document.getElementById("container")); 复制代码
Suspense只有等内部全部组件都加载完毕,才会把fallback的内容去掉,有任何一个组件处于pending状态,都会加载fallback
下文源代码中 result
function mapChildren(children, func, context) {
if (children == null) {
return children;
}
const result = [];
mapIntoWithKeyPrefixInternal(children, result, null, func, context);
return result;
}
复制代码