深刻react-基礎API(二)

前言

上一篇寫了Children,createRef,接着上一篇寫後面的幾個APIreact

React-API

const React = {
  Children: {
    map,
    forEach,
    count,
    toArray,
    only,
  },

  createRef,
  Component,
  PureComponent,

  createContext,
  forwardRef,
  lazy,
  memo,

  useCallback,
  useContext,
  useEffect,
  useImperativeHandle,
  useDebugValue,
  useLayoutEffect,
  useMemo,
  useReducer,
  useRef,
  useState,

  Fragment: REACT_FRAGMENT_TYPE,
  Profiler: REACT_PROFILER_TYPE,
  StrictMode: REACT_STRICT_MODE_TYPE,
  Suspense: REACT_SUSPENSE_TYPE,

  createElement: createElement,
  cloneElement:  cloneElement,
  createFactory: createFactory,
  isValidElement: isValidElement,

  version: ReactVersion,

  __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactSharedInternals,
};

Component

const emptyObject = {};

class Component {
  constructor(props, context, updater) {
    this.props = props;
    this.context = context;
    this.ref = emptyObject;
    this.updater = updater || null;
  }
  isReactComponent() {}

  setState(partialState, callback) {
    this.updater.enqueueSetState(this, partialState, callback, "setState");
  }
  forceUpdate(callback) {
    this.updater.enqueueForceUpdate(this, callback, "forceUpdate");
  }
}

這裏我稍微改了一下源代碼,源代碼是用的function構造函數,這裏我覺的class看着會更簡單一些,實際上是一摸同樣的,Component的源代碼在ReactBaseClasses裏dom

  • 這塊代碼比較簡單,先建立一個Component類,可接收props,context,updater三個參數
  • 並分賦值ide

    • this.props = props;
    • this.context = context;
    • this.ref = emptyObject;
    • this.updater = updater || null;
  • isReactComponent: 沒什麼特別意義,在react-dom包中會有一些地方拿原型中是否存在這個方法來判斷是否是一個class Component
  • setState:調用了this.updater.enqueueSetState,這個方法主就是setState的主要邏輯,放到react-dom中再去說,它在ReactFiberClassComponent中注入
  • forceUpdate:跟setState同樣調用了this.updater中的方法enqueueForceUpdate

補充一下源碼中可能用到了ReactNoopUpdateQueue,這個文件只是在dev中使用,僅僅給出一些提示而已函數

PureComponent

class PureComponent extends Component {
  constructor(props, context, updater) {
    super(props, context, updater);
    this.props = props;
    this.context = context;
    this.refs = emptyObject;
    this.updater = updater || null;
  }

  isPureReactComponent = true;
}
  • PureComponent和Component一摸同樣,僅僅只是多了一個標誌屬性isPureReactComponent = true

createContext

import { REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE } from "shared/ReactSymbols";

export function createContext(defaultValue, calculateChangedBits) {
  if (calculateChangedBits == undefined) {
    calculateChangedBits = null;
  }

  const context = {
    $$typeof: REACT_CONTEXT_TYPE,
    _calculateChangedBits: calculateChangedBits,
    _currentValue: defaultValue,
    _currentValue2: defaultValue,
    _threadCount: 0,
    Provider: null,
    Consumer: null
  };

  (context.Provider = {
    $$typeof: REACT_PROVIDER_TYPE,
    _context: context
  }),
    (context.Consumer = context);

  return context;
}
  • 這個方法能夠簡單的看就是返回一個對象,而對象中的內容就是以上這麼幾項,惟一值的關注的是Provider和Consumer
  • Provider 的屬性是一個$$typeof: REACT_PROVIDER_TYPE,一個symbol標誌位,react中不少對象都會有這樣一個惟一的symbol屬性,只是爲了提供在react-dom中作更新操做的時候能更好的區分和判斷類型
  • Concumer:把context整個對象都賦值給了它
  • 最後返回一個context
  • 官方的API好像沒有第二個參數calculateChangedBits,這個參數傳是一個(oldValue,newValue)=> number, 用來計算新老context的值,這個也是react-dom的內容,提早有興趣能夠看ReactFiberNewContext這個文件

forwardRef

import { REACT_FORWARD_REF_TYPE } from "shared/ReactSymbols";

export default function forwardRef(render) {
  return {
    $$typeof: REACT_FORWARD_REF_TYPE,
    render
  };
}
  • 和createRef這樣的API差很少就是返回一個對象,給一個symbol惟一屬性,react中有不少這樣的API,最終在createElement的時候會把這個對象掛在type當中

可能不少人看了很疑惑,感受看完也沒什麼用,但這就是一個看react源碼的邏輯,不要一開始就過度追求從到到尾的實現,由於react代碼不少不少,我以爲一層一層的往裏看是比較好的方法,等看完這些,到了react-dom內容的時候,慢慢的就會發現這些API裏面的屬性它究竟是作什麼用的了。oop

累了明天再寫吧this

相關文章
相關標籤/搜索