水晶儿 發表於 2022-9-26 20:19:00

React源码解析

<p>一直在用react进行编码,下面来看一下react框架的源码,了解一下react框架的思路。</p>
<p>首先,看下packages/react文件夹下的代码,也就是React</p>
<p>通过packages/react/index.js,可以大致了解到有哪些常用的react api</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">export {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
act as unstable_act,
Children,
Component,
Fragment,
Profiler,
PureComponent,
StrictMode,
Suspense,
SuspenseList,
cloneElement,
createContext,
createElement,
createFactory,
createMutableSource,
createRef,
createServerContext,
experimental_use,
forwardRef,
isValidElement,
lazy,
memo,
............
useId,
useCallback,
useContext,
useDebugValue,
useDeferredValue,
useEffect,
useImperativeHandle,
useInsertionEffect,
useLayoutEffect,
useMemo,
useMutableSource,
useSyncExternalStore,
useReducer,
useRef,
useState,
useTransition,
version,
} from </span>'./src/React';</pre>
</div>
<p>这边把自己常用的来进行分析讲解</p>
<p><span style="font-size: 16px"><strong>1. Component, pureComponent</strong></span></p>
<p>在进行类组件编写时,第一步就是进行该构造函数的继承</p>
<p>&nbsp; &nbsp; &nbsp; question: 什么时候要使用pureComponent? pureComponent有什么注意事项吗?</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">class TestCom extends React.Component
or
class TestCom extends React.PureComponent</span></pre>
</div>
<p>源码如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">import {Component, PureComponent} from './ReactBaseClasses';</span>

<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Component(props, context, updater) {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.props =<span style="color: rgba(0, 0, 0, 1)"> props;
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.context =<span style="color: rgba(0, 0, 0, 1)"> context;
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.refs = emptyObject; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> {}</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> We initialize the default updater but the real one gets injected by the</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> renderer.</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.updater = updater ||<span style="color: rgba(0, 0, 0, 1)"> ReactNoopUpdateQueue;
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">上面代码中,constructor()、toString()、toValue()这三个方法,其实都是定义在Component.prototype上面。</span>


<span style="color: rgba(0, 128, 0, 1)">//eg:</span><span style="color: rgba(0, 128, 0, 1)"> 在继承时,使用class引入,写法更加清晰</span>
<span style="color: rgba(0, 0, 0, 1)">class TestCom extends React.Component {
constructor (props) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 构造方法,没写的时候默认执行</span>
<span style="color: rgba(0, 0, 0, 1)">    super(props)
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 调用父类的constructor(props)</span>
   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> constructor默认返回实例对象(this)</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在super之后才能使用this,例如this.state</span>
<span style="color: rgba(0, 0, 0, 1)">}
}</span></pre>
</div>
<pre><span>ReactNoopUpdateQueue是一个对象,上面有一些方法,是用于对一些错误信息得提示<br></span></pre>
<div class="cnblogs_code">
<pre>ReactNoopUpdateQueue =<span style="color: rgba(0, 0, 0, 1)"> {
isMounted: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(publicInstance) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
},
enqueueForceUpdate: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(publicInstance, callback,
    callerName) {
    warnNoop(publicInstance, </span>'forceUpdate'<span style="color: rgba(0, 0, 0, 1)">);
},
enqueueReplaceState: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){},
enqueueSetState: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {}
}

warnNoop() {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 进行一些错误信息得提示</span>
   const constructor =<span style="color: rgba(0, 0, 0, 1)"> publicInstance.constructor;
    const componentName </span>=<span style="color: rgba(0, 0, 0, 1)">
      (constructor </span>&amp;&amp; (constructor.displayName || constructor.name)) ||
      'ReactClass'<span style="color: rgba(0, 0, 0, 1)">;
    const warningKey </span>=<span style="color: rgba(0, 0, 0, 1)"> `${componentName}.${callerName}`;
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (didWarnStateUpdateForUnmountedComponent) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    console.error(..........);
    didWarnStateUpdateForUnmountedComponent </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p>&nbsp;</p>
<pre><span>&nbsp;</span></pre>
<p>&nbsp;</p>
<pre><span>&nbsp;</span></pre>
<p><span style="color: rgba(255, 0, 0, 1)">在Component原型上绑定了setState, forceUpdate方法</span></p>
<p><strong><span style="color: rgba(0, 0, 0, 1)">setState</span></strong></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>Component.prototype.setState = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(partialState, callback) {
   </span><span style="color: rgba(0, 0, 255, 1)">this</span>.updater.enqueueSetState(<span style="color: rgba(0, 0, 255, 1)">this</span>, partialState, callback, 'setState'<span style="color: rgba(0, 0, 0, 1)">);
};
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> this.setState({name: 'test'})</span>
<span style="color: rgba(0, 0, 0, 1)">
enqueueSetState: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(
    publicInstance,
    partialState, </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 需要更新得state -&gt; name: 'test'</span>
<span style="color: rgba(0, 0, 0, 1)">    callback,
    callerName,
) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这里没有对partialState进行更新</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> 源码注释也进行了说明:不能保证对 `setState` 的调用会同步运行,因为它们最终可能会被批量处理,因为您的函数可能在 receiveProps 之后调用</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> shouldComponentUpdate,这个新的 state、props 和 context 还不会分配给这个</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> ps: 但是并不是这里对于new state更新</span>
    warnNoop(publicInstance, 'setState'<span style="color: rgba(0, 0, 0, 1)">);
},

setState(updater[, callback])
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">setState() 的第二个参数为可选的回调函数,它将在 setState 完成合并并重新渲染组件后执行</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.setState((state, props) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> state,props接受得都保证为最新</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> {counter: state.counter +<span style="color: rgba(0, 0, 0, 1)"> props.step};
});</span></pre>
</div>
<p><span style="font-size: 14px">上述对于setState的代码感觉并没有发现对于机制的执行,全局搜索时,发现有</span>enqueueSetState,是什么时候执行的,起的什么作用呢</p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>const classComponentUpdater =<span style="color: rgba(0, 0, 0, 1)"> {
enqueueSetState(inst, payload, callback) {
    const fiber </span>= getInstance(inst); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> key._reactInternals</span>
    const eventTime = requestEventTime(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取时间</span>
    const lane =<span style="color: rgba(0, 0, 0, 1)"> requestUpdateLane(fiber);

}

}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> requestUpdateLane() 事件队列</span>
export <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> requestUpdateLane(fiber: Fiber): Lane {

}</span></pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>forceUpdate:对于组件的强制更新</strong></p>
<div class="cnblogs_code">
<pre>Component.prototype.forceUpdate = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(callback) {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.updater.enqueueForceUpdate(<span style="color: rgba(0, 0, 255, 1)">this</span>, callback, 'forceUpdate'<span style="color: rgba(0, 0, 0, 1)">);
};

enqueueForceUpdate: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(publicInstance, callback, callerName) {
    warnNoop(publicInstance, </span>'forceUpdate'<span style="color: rgba(0, 0, 0, 1)">);
},
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当状态更新时,但未调用setState, 这不会调用`shouldComponentUpdate`,但会调用`componentWillUpdate` 和 `componentDidUpdate`</span></pre>
</div>
<p>&nbsp;question : 重点:这里并没有进行一些其他的操作,只是调用warnNoop,是怎么进行了功能的实现?</p>
<p>-----------------------------------------------------------------------------待回答----------------------------------------------</p>
<p>&nbsp;</p>
<p><strong><span style="color: rgba(0, 0, 0, 1); font-size: 16px">PureComponent</span></strong></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> PureComponent(props, context, updater) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 与Component相同</span>
<span style="color: rgba(0, 0, 0, 1)">}
const pureComponentPrototype </span>= (PureComponent.prototype = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ComponentDummy());
pureComponentPrototype.constructor </span>=<span style="color: rgba(0, 0, 0, 1)"> PureComponent;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将Component的原型赋值给PureComponent,并且将其constructor属性更改为PureComponent </span>

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 避免这些方法的额外原型跳转</span>
<span style="color: rgba(0, 0, 0, 1)">assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent </span>= <span style="color: rgba(0, 0, 255, 1)">true</span>;</pre>
</div>
<p>&nbsp;</p>
<p>Component与PureComponent类基本相同,唯一的区别是PureComponent上多了一个标识isPureReactComponent</p>
<p>// react-reconciler</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> checkShouldComponentUpdate() </span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> 检查组件是否需要更新,</span>
<span style="color: rgba(0, 0, 0, 1)">checkShouldComponentUpdate(.....) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (ctor.prototype &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> ctor.prototype.isPureReactComponent) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 对于PureComponent而言,当state和props未更新时,组件不重新渲染</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>!shallowEqual(oldProps, newProps) || !<span style="color: rgba(0, 0, 0, 1)">shallowEqual(oldState, newState)
    );
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
} </span></pre>
</div>
<p>但是在使用PureComponent 过程中,避免出现props中引用类型,虽然props发生变化但地址未变,导致虽然props更新但组件未更新的bug.</p>
<div>&nbsp;</div>
<div><span style="font-size: 16px"><strong>2.Fragment</strong></span></div>
<div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">export { REACT_FRAGMENT_TYPE as Fragment}

export const REACT_FRAGMENT_TYPE </span>= Symbol.<span style="color: rgba(0, 0, 255, 1)">for</span>('react.fragment'); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Symbol(react.fragment) 只是一个占位符?</span></pre>
</div>
<p>&nbsp;</p>
</div>
<div><span style="font-size: 16px"><strong>3.&nbsp;createContext</strong></span></div>
<div><span style="font-size: 16px"><span style="font-size: 14px">context提供了一种无需为每层组件手动添加props,就能在组件树间进行数据传递的方法</span></span></div>
<div>
<div class="cnblogs_code">
<pre>export <span style="color: rgba(0, 0, 255, 1)">function</span> createContext&lt;T&gt;(defaultValue: T): ReactContext&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)"> {
const context: ReactContext</span>&lt;T&gt; =<span style="color: rgba(0, 0, 0, 1)"> {
    $$</span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">: REACT_CONTEXT_TYPE,
    _currentValue: defaultValue,
    _currentValue2: defaultValue,
    _threadCount: </span>0<span style="color: rgba(0, 0, 0, 1)">,
    Provider: (</span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">: any),
    Consumer: (</span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">: any),
    _defaultValue: (</span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">: any),
    _globalName: (</span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">: any),
};

context.Provider </span>=<span style="color: rgba(0, 0, 0, 1)"> {
    $$</span><span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">: REACT_PROVIDER_TYPE,
    _context: context,
};
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> context;
}</span></pre>
</div>
<p><span style="font-size: 16px"><strong>4.createRef</strong></span></p>
<p><span style="font-size: 14px"><code class="gatsby-code-text">React.createRef</code>&nbsp;创建一个能够通过 ref 属性附加到 React 元素的&nbsp;ref。</span></p>
</div>
<div>
<div class="cnblogs_code">
<pre>export <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> createRef(): RefObject {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建一个具有current:null 属性的对象</span>
const refObject =<span style="color: rgba(0, 0, 0, 1)"> {
    current: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
};
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (__DEV__) {
    Object.seal(refObject);
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> refObject;
}</span></pre>
</div>
<p><span style="font-size: 16px"><strong>5.memo</strong></span></p>
<p><span style="font-size: 14px">React.memo为高阶组件</span></p>
<p><span style="font-size: 14px">你的组件在相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在&nbsp;<code class="gatsby-code-text">React.memo</code>&nbsp;中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现</span></p>
<div class="cnblogs_code">
<pre>export <span style="color: rgba(0, 0, 255, 1)">function</span> memo&lt;Props&gt;<span style="color: rgba(0, 0, 0, 1)">(
type: React$ElementType,
compare</span>?: (oldProps: Props, newProps: Props) =&gt; <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)">,
) {
   </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> $$typeof属性是为了虚拟dom的安全性</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 使用Symbol标记每个React元素,减少xss攻击</span>
    $$<span style="color: rgba(0, 0, 255, 1)">typeof</span>: REACT_MEMO_TYPE, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Symbol.for('react.memo');</span>
<span style="color: rgba(0, 0, 0, 1)">    type,
    compare: compare </span>=== undefined ? <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)"> : compare,
};
}</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-size: 16px"><strong>6.&nbsp;useCallback与useMemo</strong></span></p>
<p><code class="gatsby-code-text">useCallback(fn, deps)</code>&nbsp;相当于&nbsp;<code class="gatsby-code-text">useMemo(() =&gt; fn, deps)</code>。</p>
<div class="cnblogs_code">
<pre>export <span style="color: rgba(0, 0, 255, 1)">function</span> useCallback&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)">(
callback: T,
deps: Array</span>&lt;mixed&gt; | <span style="color: rgba(0, 0, 255, 1)">void</span> | <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
): T {
const dispatcher </span>=<span style="color: rgba(0, 0, 0, 1)"> resolveDispatcher();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> dispatcher.useCallback(callback, deps);
}

export </span><span style="color: rgba(0, 0, 255, 1)">function</span> useMemo&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)">(
create: () </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> T,
deps: Array</span>&lt;mixed&gt; | <span style="color: rgba(0, 0, 255, 1)">void</span> | <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
): T {
const dispatcher </span>=<span style="color: rgba(0, 0, 0, 1)"> resolveDispatcher();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> dispatcher.useMemo(create, deps);
}

const memoizedCallback </span>=<span style="color: rgba(0, 0, 0, 1)"> useCallback(
() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    doSomething(a, b);
},
,
);</span></pre>
</div>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>export <span style="color: rgba(0, 0, 255, 1)">function</span> useCallback&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)">(
callback: T,
deps: Array</span>&lt;mixed&gt; | <span style="color: rgba(0, 0, 255, 1)">void</span> | <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
): T {
const dispatcher </span>=<span style="color: rgba(0, 0, 0, 1)"> resolveDispatcher();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> dispatcher.useCallback(callback, deps);
}


const memoizedCallback </span>=<span style="color: rgba(0, 0, 0, 1)"> useCallback(
() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    doSomething(a, b);
},
,
);</span></pre>
</div>
<p>&nbsp;</p>
<p>7.createElement</p>
<p>react中<code>JSX</code>在编译时会被<code>Babel</code>编译为<code>React.createElement</code>方法</p>
<p>即使文件中没使用其他引用,在文件开头也需要引入 import React from 'react'</p>
<p>来看一下相关createElement的源码</p>
<div class="cnblogs_code">
<pre>export <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> createElement(type, config, children) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> type-&gt; 元素类型 config -&gt; 元素配置(一些类名等) children -&gt; 子元素(该元素下的子元素)</span>
<span style="color: rgba(0, 0, 0, 1)">let propName;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Reserved names are extracted</span>
const props =<span style="color: rgba(0, 0, 0, 1)"> {};

let key </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
let ref </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
let self </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
let source </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">if</span> (config != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将config处理后赋值给props</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ..........</span>
<span style="color: rgba(0, 0, 0, 1)">}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 子对象可以是多个参数,它们被转移到新分配的props对象上。</span>
const childrenLength = arguments.length - 2<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (childrenLength === 1<span style="color: rgba(0, 0, 0, 1)">) {
    props.children </span>=<span style="color: rgba(0, 0, 0, 1)"> children;
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (childrenLength &gt; 1<span style="color: rgba(0, 0, 0, 1)">) {
    const childArray </span>=<span style="color: rgba(0, 0, 0, 1)"> Array(childrenLength);
    </span><span style="color: rgba(0, 0, 255, 1)">for</span> (let i = 0; i &lt; childrenLength; i++<span style="color: rgba(0, 0, 0, 1)">) {
      childArray </span>= arguments;
    }
    props.children </span>=<span style="color: rgba(0, 0, 0, 1)"> childArray;
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Resolve default props</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (type &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> type.defaultProps) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ............</span>
<span style="color: rgba(0, 0, 0, 1)">}
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
);
}</span></pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;看了一下,很多地方还是没有真正的理解,等后面再读一遍的时候再进行整理补充吧</p>
<p>待续</p>
<p>&nbsp;</p>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/best-mll/p/16732274.html
頁: [1]
查看完整版本: React源码解析