閱讀react源碼:(一).組件的實(shí)例化,元素掛載揍堕,重繪render

react版本:
15.6-dev
文件名:
ReactCompositeComponent.js
路徑:
react/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js
github地址:
https://github.com/facebook/react/blob/15.6-dev/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js

源碼(ReactCompositeComponent.js)

'use strict';  
  
var _prodInvariant = require('./reactProdInvariant'),// 生產(chǎn)環(huán)境React形式帶url報錯   
    _assign = require('object-assign');  
  
var React = require('react/lib/React');  
  
// 提供ReactComponentEnvironment.replaceNodeWithMarkup方法料身,用于替換掛載的Dom元素  
var ReactComponentEnvironment = require('./ReactComponentEnvironment');  
  
// 開發(fā)環(huán)境下,ReactClass組件被實(shí)例化或其render方法被調(diào)用時衩茸,向ReactCurrentOwner.current添加當(dāng)前實(shí)例this  
// 實(shí)例化完成或render方法執(zhí)行完成芹血,ReactCurrentOwner.current置為null  
var ReactCurrentOwner = require('react/lib/ReactCurrentOwner');  
  
// 調(diào)試用  
var ReactErrorUtils = require('./ReactErrorUtils');  
  
// 以對象形式存儲組件實(shí)例  
var ReactInstanceMap = require('./ReactInstanceMap');  
  
// 調(diào)試用  
var ReactInstrumentation = require('./ReactInstrumentation');  
  
// 用于判斷節(jié)點(diǎn)類型,ReactComponentElement元素返回1;ReactDomElement元素返回0幔烛;若為空啃擦,返回2  
var ReactNodeTypes = require('./ReactNodeTypes');  
  
// 用于掛載、移除饿悬、更新組件實(shí)例令蛉,作為方法的發(fā)起者,如ReactReconciler.mountComponent  
var ReactReconciler = require('./ReactReconciler');  
  
if (process.env.NODE_ENV !== 'production') {  
  var checkReactTypeSpec = require('./checkReactTypeSpec');  
}  
  
// 空對象狡恬,并且用Object.freeze凍結(jié)為不可修改珠叔、不可擴(kuò)展  
var emptyObject = require('fbjs/lib/emptyObject');  
  
// invariant(condition,format,a,b,c,d,e,f) condition為否值,替換format中的"%s"弟劲,并throw error報錯    
var invariant = require('fbjs/lib/invariant');  
  
// shallowEqual(A,B)比較值相等祷安,及淺比較鍵值相等  
var shallowEqual = require('fbjs/lib/shallowEqual');  
  
// 判斷組件重繪時是采用更新組件實(shí)例的方式(返回真值);還是采用銷毀實(shí)例后兔乞、重新創(chuàng)建實(shí)例的方式(返回否值)  
// 組件元素的構(gòu)造函數(shù)或key值不同汇鞭,銷毀實(shí)例后再行創(chuàng)建  
var shouldUpdateReactComponent = require('./shouldUpdateReactComponent');  
  
// warning(condition,format) condition為否值,替換format中的"%s"庸追,并console.error警告   
var warning = require('fbjs/lib/warning');  
  
// 區(qū)分純函數(shù)無狀態(tài)組件霍骄、PureComponent純組件、Component組件的標(biāo)識符  
var CompositeTypes = {  
  ImpureClass: 0,// 組件淡溯,繼承自React.Component  
  PureClass: 1,// 純組件读整,繼承自React.PureComponent,不能設(shè)置shouldComponentUpdate方法血筑,重繪時判斷props绘沉、state是否變更  
  StatelessFunctional: 2// 純函數(shù)無狀態(tài)組件,function(props,context,updateQueue){}形式  
};  
  
// 將無狀態(tài)組件function(props,context,updateQueue){}包裝為帶有render原型方法的構(gòu)造函數(shù)形式  
function StatelessComponent(Component) {}  
StatelessComponent.prototype.render = function () {  
  var Component = ReactInstanceMap.get(this)._currentElement.type;  
  var element = Component(this.props, this.context, this.updater);  
  warnIfInvalidElement(Component, element);  
  return element;  
};  
  
// 校驗(yàn)無狀態(tài)組件返回值必須是ReactElement豺总,以及不能設(shè)置childContextTypes靜態(tài)屬性  
function warnIfInvalidElement(Component, element) {  
  if (process.env.NODE_ENV !== 'production') {  
    process.env.NODE_ENV !== 'production' ?   
      warning(element === null || element === false || React.isValidElement(element),   
        '%s(...): A valid React element (or null) must be returned. You may have '   
        + 'returned undefined, an array or some other invalid object.',   
        Component.displayName || Component.name || 'Component')   
      : void 0;  
    process.env.NODE_ENV !== 'production' ?   
      warning(!Component.childContextTypes,   
        '%s(...): childContextTypes cannot be defined on a functional component.',   
        Component.displayName || Component.name || 'Component')   
      : void 0;  
  }  
}  
  
// 校驗(yàn)是否純組件或組件车伞;返回否值,當(dāng)作非狀態(tài)組件喻喳、或ReactClass的工廠函數(shù)處理  
function shouldConstruct(Component) {  
  return !!(Component.prototype && Component.prototype.isReactComponent);  
}  
  
function isPureComponent(Component) {  
  return !!(Component.prototype && Component.prototype.isPureReactComponent);  
}  
  
// 開發(fā)環(huán)境下帶調(diào)試方式執(zhí)行fn  
function measureLifeCyclePerf(fn, debugID, timerType) {  
  if (debugID === 0) {  
    // Top-level wrappers (see ReactMount) and empty components (see  
    // ReactDOMEmptyComponent) are invisible to hooks and devtools.  
    // Both are implementation details that should go away in the future.  
    return fn();  
  }  
  
  ReactInstrumentation.debugTool.onBeginLifeCycleTimer(debugID, timerType);  
  try {  
    return fn();  
  } finally {  
    ReactInstrumentation.debugTool.onEndLifeCycleTimer(debugID, timerType);  
  }  
}  
  
var nextMountID = 1;  
  
// 自定義組件實(shí)例化另玖、掛載、移除表伦、更新實(shí)現(xiàn)  
var ReactCompositeComponent = {  
  // 實(shí)例化  
  construct: function (element) {  
    this._currentElement = element;// ReactComponentElement谦去,配置了組件的構(gòu)造函數(shù)、props屬性等  
    this._rootNodeID = 0;  
    this._compositeType = null;// 區(qū)分純函數(shù)無狀態(tài)組件蹦哼、繼承自PureComponent的純組件鳄哭、以及繼承自Component的組件  
    this._instance = null;// ReactComponent實(shí)例  
    this._hostParent = null;// 文檔元素,作為組件元素的父節(jié)點(diǎn)  
    this._hostContainerInfo = null;  
  
    // See ReactUpdateQueue  
    this._updateBatchNumber = null;  
    this._pendingElement = null;// ReactDom.render方法渲染時包裹元素由react組件渲染纲熏,_pendingElement存儲待渲染元素  
    this._pendingStateQueue = null;// 組件調(diào)用setState妆丘、replaceState方法锄俄,通過ReactUpdateQueue將更迭后的state推入_pendingStateQueue  
    this._pendingReplaceState = false;// 判斷組件是否通過調(diào)用replaceState方法向_pendingStateQueue推入state數(shù)據(jù)  
    this._pendingForceUpdate = false;// 組件調(diào)用forceUpdate賦值為真  
  
    this._renderedNodeType = null;// 節(jié)點(diǎn)類型,區(qū)分ReactComponentElement勺拣、ReactDomElement元素  
    this._renderedComponent = null;// render方法內(nèi)子組件實(shí)例  
    this._context = null;// 賦值給組件的context屬性  
    this._mountOrder = 0;// 掛載的第幾個組件  
    this._topLevelWrapper = null;  
  
    // See ReactUpdates and ReactUpdateQueue.  
    this._pendingCallbacks = null;  
  
    // ComponentWillUnmount shall only be called once  
    this._calledComponentWillUnmount = false;  
  
    if (process.env.NODE_ENV !== 'production') {  
      this._warnedAboutRefsInRender = false;  
    }  
  },  
  
  // 由ReactReconciler.mountComponent方法發(fā)起  
  
  // 關(guān)于參數(shù):  
  // 參數(shù)transaction默認(rèn)為ReactUpdates.ReactReconcileTransaction奶赠,即ReactReconcileTransaction模塊  
  //    用于在組件元素掛載前后執(zhí)行指定的鉤子函數(shù),選中文本回撤药有、阻止事件觸發(fā)毅戈、生命周期鉤子和調(diào)試等  
  //    特別是通過執(zhí)行g(shù)etReactMountReady().enqueue()方法,添加componentDidMount愤惰、componentDidUpdate生命周期鉤子  
  //    其次是通過執(zhí)行g(shù)etUpdateQueue()方法苇经,向組件實(shí)例注入updater參數(shù),默認(rèn)是ReactUpdateQueue模塊  
  //    意義是為組件的setState羊苟、replaceState塑陵、forceUpdate方法完成功能提供必要的函數(shù)  
  // 參數(shù)context或者為空對象感憾,或者由上層組件提供蜡励,后者混合this.context和this.getChildContext()形成  
  
  // 完成組件實(shí)例化,執(zhí)行實(shí)例的render方法阻桅,通過ReactDomComponent繪制DomLazyTree凉倚,掛載componentDidMount函數(shù)  
  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {  
    var _this = this;  
  
    this._context = context;  
    this._mountOrder = nextMountID++;  
    this._hostParent = hostParent;  
    this._hostContainerInfo = hostContainerInfo;  
  
    // 添加到ReactComponentElement元素的props屬性  
    var publicProps = this._currentElement.props;  
  
    // 通過Component.contextTypes過濾由上層組件注入的context屬性,并做校驗(yàn)  
    var publicContext = this._processContext(context);  
  
    // 純函數(shù)無狀態(tài)組件嫂沉、或者繼承自PureComponent的純組件構(gòu)造函數(shù)稽寒、或者繼承自Component的組件構(gòu)造函數(shù)  
    var Component = this._currentElement.type;  
  
    // 傳入組件ReactComponent的第三個參數(shù)updater,默認(rèn)是ReactUpdateQueue模塊趟章,用于實(shí)現(xiàn)setState等方法  
    var updateQueue = transaction.getUpdateQueue();  
  
    // 校驗(yàn)是否純組件或組件杏糙;返回否值,當(dāng)作非狀態(tài)組件蚓土、或ReactClass的工廠函數(shù)處理  
    var doConstruct = shouldConstruct(Component);  
  
    // 創(chuàng)建純組件或組件實(shí)例宏侍,或者獲取無狀態(tài)組件的返回值  
    var inst = this._constructComponent(doConstruct, publicProps, publicContext, updateQueue);  
  
    // 待掛載的ReactComponentElement元素  
    var renderedElement;  
  
    // Component為純函數(shù)無狀態(tài)組件書寫方式  
    if (!doConstruct && (inst == null || inst.render == null)) {  
      // 無狀態(tài)組件返回值即是待掛載的ReactElement  
      renderedElement = inst;  
  
      // 校驗(yàn)無狀態(tài)組件返回值必須是ReactElement,以及不能設(shè)置childContextTypes靜態(tài)屬性  
      warnIfInvalidElement(Component, renderedElement);  
  
      // 校驗(yàn)無狀態(tài)組件的返回值是否ReactElement  
      !(inst === null || inst === false || React.isValidElement(inst)) ?   
        process.env.NODE_ENV !== 'production' ?   
          invariant(false, '%s(...): A valid React element (or null) must be returned. '   
            + 'You may have returned undefined, an array or some other invalid object.',   
            Component.displayName || Component.name || 'Component')   
          : _prodInvariant('105', Component.displayName || Component.name || 'Component')   
          : void 0;  
        
      // 將無狀態(tài)組件function(props,context,updateQueue){}包裝為帶有render原型方法的構(gòu)造函數(shù)形式  
      inst = new StatelessComponent(Component);  
  
      // 添加無狀態(tài)組件標(biāo)識  
      this._compositeType = CompositeTypes.StatelessFunctional;  
  
    // Component為純組件或組件形式  
    } else {  
      if (isPureComponent(Component)) {  
        // 添加純組件標(biāo)識  
        this._compositeType = CompositeTypes.PureClass;  
      } else {  
        // 添加組件標(biāo)識  
        this._compositeType = CompositeTypes.ImpureClass;  
      }  
    }  
  
    // 實(shí)例沒有render方法蜀漆,或者props屬性同publicProps不符谅河,警告  
    if (process.env.NODE_ENV !== 'production') {  
      if (inst.render == null) {  
        process.env.NODE_ENV !== 'production' ?   
          warning(false, '%s(...): No `render` method found on the returned component '   
            + 'instance: you may have forgotten to define `render`.',   
            Component.displayName || Component.name || 'Component')   
          : void 0;  
      }  
  
      var propsMutated = inst.props !== publicProps;  
      var componentName = Component.displayName || Component.name || 'Component';  
  
      process.env.NODE_ENV !== 'production' ?   
        warning(inst.props === undefined || !propsMutated,   
          '%s(...): When calling super() in `%s`, make sure to pass '   
          + 'up the same props that your component\'s constructor was passed.',   
          componentName, componentName)   
        : void 0;  
    }  
  
    // 原本作為構(gòu)造函數(shù)的參數(shù)傳入,為方便起見确丢,再次賦值绷耍,同時保證實(shí)例數(shù)據(jù)的準(zhǔn)確性  
    inst.props = publicProps;  
    inst.context = publicContext;  
    inst.refs = emptyObject;  
    inst.updater = updateQueue;  
  
    this._instance = inst;  
  
    // ReactInstanceMap中添加組件實(shí)例  
    ReactInstanceMap.set(inst, this);  
  
    if (process.env.NODE_ENV !== 'production') {  
      // 組件不是由ReactClass方式創(chuàng)建,且添加了getInitialState或getDefaultProps方法鲜侥,警告  
      process.env.NODE_ENV !== 'production' ?   
        warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved || inst.state,   
          'getInitialState was defined on %s, a plain JavaScript class. '   
          + 'This is only supported for classes created using React.createClass. '   
          + 'Did you mean to define a state property instead?',   
          this.getName() || 'a component')   
        : void 0;  
      process.env.NODE_ENV !== 'production' ?   
        warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved,   
          'getDefaultProps was defined on %s, a plain JavaScript class. '   
          + 'This is only supported for classes created using React.createClass. '   
          + 'Use a static property to define defaultProps instead.',   
          this.getName() || 'a component')   
        : void 0;  
  
      // 靜態(tài)屬性propTypes褂始、contextTypes書寫為原型屬性提示,只構(gòu)造函數(shù)擁有描函,實(shí)例沒有  
      process.env.NODE_ENV !== 'production' ?   
        warning(!inst.propTypes,   
          'propTypes was defined as an instance property on %s. Use a static '   
          + 'property to define propTypes instead.', this.getName() || 'a component')   
        : void 0;  
      process.env.NODE_ENV !== 'production' ?   
        warning(!inst.contextTypes,   
          'contextTypes was defined as an instance property on %s. Use a '   
          + 'static property to define contextTypes instead.', this.getName() || 'a component')   
        : void 0;  
  
      // 接口變動更改  
      process.env.NODE_ENV !== 'production' ?   
        warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called '   
          + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? '   
          + 'The name is phrased as a question because the function is '   
          + 'expected to return a value.', this.getName() || 'A component')   
        : void 0;  
      process.env.NODE_ENV !== 'production' ?   
        warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called '   
          + 'componentDidUnmount(). But there is no such lifecycle method. '   
          + 'Did you mean componentWillUnmount()?', this.getName() || 'A component')   
        : void 0;  
      process.env.NODE_ENV !== 'production' ?   
        warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called '   
          + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',   
          this.getName() || 'A component')   
        : void 0;  
    }  
  
    // 獲取初始state崎苗,并提示state只能設(shè)置為對象形式  
    var initialState = inst.state;  
    if (initialState === undefined) {  
      inst.state = initialState = null;  
    }  
    !(typeof initialState === 'object' && !Array.isArray(initialState)) ?   
      process.env.NODE_ENV !== 'production' ?   
        invariant(false, '%s.state: must be set to an object or null',   
          this.getName() || 'ReactCompositeComponent')   
        : _prodInvariant('106', this.getName() || 'ReactCompositeComponent')   
      : void 0;  
  
    this._pendingStateQueue = null;  
    this._pendingReplaceState = false;  
    this._pendingForceUpdate = false;  
  
    // 執(zhí)行實(shí)例inst的render方法搂赋,嵌套調(diào)用mountComponent,將返回值ReactNode元素轉(zhuǎn)化成DomLazyTree輸出  
    var markup;  
    if (inst.unstable_handleError) {  
      markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);  
    } else {  
      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);  
    }  
  
    // 向后置鉤子transaction.getReactMountReady()中添加實(shí)例的生命周期方法componentDidMount  
    if (inst.componentDidMount) {  
      if (process.env.NODE_ENV !== 'production') {  
        transaction.getReactMountReady().enqueue(function () {  
          measureLifeCyclePerf(function () {  
            return inst.componentDidMount();  
          }, _this._debugID, 'componentDidMount');  
        });  
      } else {  
        transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);  
      }  
    }  
  
    return markup;  
  },  
  
  // 創(chuàng)建純組件或組件實(shí)例益缠,或者獲取無狀態(tài)組件的返回值  
  _constructComponent: function (doConstruct, publicProps, publicContext, updateQueue) {  
    if (process.env.NODE_ENV !== 'production') {  
      ReactCurrentOwner.current = this;  
      try {  
        // 創(chuàng)建純組件或組件實(shí)例脑奠,或者獲取無狀態(tài)組件的返回值  
        return this._constructComponentWithoutOwner(doConstruct, publicProps, publicContext, updateQueue);  
      } finally {  
        ReactCurrentOwner.current = null;  
      }  
    } else {  
      return this._constructComponentWithoutOwner(doConstruct, publicProps, publicContext, updateQueue);  
    }  
  },  
  
  // 創(chuàng)建純組件或組件實(shí)例,或者獲取無狀態(tài)組件的返回值  
  _constructComponentWithoutOwner: function (doConstruct, publicProps, publicContext, updateQueue) {  
    var Component = this._currentElement.type;  
  
    // Component為純組件或組件幅慌,創(chuàng)建實(shí)例宋欺;Component可能為TopLevelWrapper  
    if (doConstruct) {  
      if (process.env.NODE_ENV !== 'production') {  
        return measureLifeCyclePerf(function () {  
          return new Component(publicProps, publicContext, updateQueue);  
        }, this._debugID, 'ctor');  
      } else {  
        return new Component(publicProps, publicContext, updateQueue);  
      }  
    }  
  
    // Component為工廠函數(shù)ReactClassFacory=function(props,context,updateQueue){  
    //     return new ReactClass(props,context,updateQueue)     
    // }  
    // 或者,無狀態(tài)組件純函數(shù)形式function(props,context,updateQueue){}  
    if (process.env.NODE_ENV !== 'production') {  
      return measureLifeCyclePerf(function () {  
        return Component(publicProps, publicContext, updateQueue);  
      }, this._debugID, 'render');  
    } else {  
      return Component(publicProps, publicContext, updateQueue);  
    }  
  },  
  
  performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {  
    var markup;  
    var checkpoint = transaction.checkpoint();  
    try {  
      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);  
    } catch (e) {  
      // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint  
      transaction.rollback(checkpoint);  
      this._instance.unstable_handleError(e);  
      if (this._pendingStateQueue) {  
        // _processPendingState方法獲取組件setState胰伍、replaceState方法執(zhí)行后的最終state  
        this._instance.state = this._processPendingState(this._instance.props, this._instance.context);  
      }  
      checkpoint = transaction.checkpoint();  
  
      this._renderedComponent.unmountComponent(true);  
      transaction.rollback(checkpoint);  
  
      // Try again - we've informed the component about the error, so they can render an error message this time.  
      // If this throws again, the error will bubble up (and can be caught by a higher error boundary).  
      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);  
    }  
    return markup;  
  },  
  
  // 執(zhí)行ReactComponent實(shí)例的render方法齿诞,獲取其返回值ReactNode  
  // 嵌套調(diào)用mountComponent,完成ReactNode元素相應(yīng)組件的實(shí)例化和render方法執(zhí)行  
  // 最終通過ReactDomElement轉(zhuǎn)化為DOMLazyTree對象輸出骂租,其node屬性為需要插入文檔dom對象  
  performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {  
    var inst = this._instance;  
  
    var debugID = 0;  
    if (process.env.NODE_ENV !== 'production') {  
      debugID = this._debugID;  
    }  
  
    // 執(zhí)行組件實(shí)例的componentWillMount方法  
    // componentWillMount方法內(nèi)調(diào)用setState祷杈、replaceState,_pendingStateQueue有值渗饮,刷新state后再行繪制  
    if (inst.componentWillMount) {  
      if (process.env.NODE_ENV !== 'production') {  
        measureLifeCyclePerf(function () {  
          return inst.componentWillMount();  
        }, debugID, 'componentWillMount');  
      } else {  
        inst.componentWillMount();  
      }  
  
      if (this._pendingStateQueue) {  
        // _processPendingState方法獲取組件setState但汞、replaceState方法執(zhí)行后的最終state  
        inst.state = this._processPendingState(inst.props, inst.context);  
      }  
    }  
  
    // 間接執(zhí)行ReactClass或TopLevelWrapper實(shí)例的render方法,獲取待掛載的元素ReactNode  
    // 組件若為函數(shù)式無狀態(tài)組件function(props,context,updateQueue){}互站,renderedElement由傳參提供  
    if (renderedElement === undefined) {  
      // 調(diào)用組件實(shí)例inst的render方法私蕾,獲取待掛載的元素ReactNode  
      renderedElement = this._renderValidatedComponent();  
    }  
  
    // 節(jié)點(diǎn)類型,ReactComponentElement元素返回1胡桃;ReactDomElement元素返回0踩叭;若為空,返回2  
    var nodeType = ReactNodeTypes.getType(renderedElement);  
    this._renderedNodeType = nodeType;  
  
    // 調(diào)用instantiateReactComponent模塊以實(shí)例化render方法的返回值翠胰,即renderedElement元素  
    var child = this._instantiateReactComponent(renderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */  
    );  
  
    // render方法內(nèi)子組件實(shí)例  
    this._renderedComponent = child;  
  
    // 嵌套調(diào)用mountComponent容贝,完成renderedElement元素相應(yīng)組件的實(shí)例化及render方法執(zhí)行  
    // 最終通過ReactDomElement轉(zhuǎn)化為DOMLazyTree對象輸出,其node屬性為需要插入文檔dom對象  
    var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context), debugID);  
  
    if (process.env.NODE_ENV !== 'production') {  
      if (debugID !== 0) {  
        var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];  
        ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);  
      }  
    }  
  
    return markup;  
  },  
  
  // 由render方法內(nèi)子組件實(shí)例之景,通過ReactDomComponent等斤富,獲取相應(yīng)的dom節(jié)點(diǎn)  
  getHostNode: function () {  
    return ReactReconciler.getHostNode(this._renderedComponent);  
  },  
  
  // 移除組件,執(zhí)行componentWillUnmount方法  
  unmountComponent: function (safely) {  
    if (!this._renderedComponent) {  
      return;  
    }  
  
    var inst = this._instance;  
  
    if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {  
      inst._calledComponentWillUnmount = true;  
  
      if (safely) {  
        var name = this.getName() + '.componentWillUnmount()';  
        ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));  
      } else {  
        if (process.env.NODE_ENV !== 'production') {  
          measureLifeCyclePerf(function () {  
            return inst.componentWillUnmount();  
          }, this._debugID, 'componentWillUnmount');  
        } else {  
          inst.componentWillUnmount();  
        }  
      }  
    }  
  
    if (this._renderedComponent) {  
      ReactReconciler.unmountComponent(this._renderedComponent, safely);  
      this._renderedNodeType = null;  
      this._renderedComponent = null;  
      this._instance = null;  
    }  
  
    this._pendingStateQueue = null;  
    this._pendingReplaceState = false;  
    this._pendingForceUpdate = false;  
    this._pendingCallbacks = null;  
    this._pendingElement = null;  
  
    this._context = null;  
    this._rootNodeID = 0;  
    this._topLevelWrapper = null;  
  
    ReactInstanceMap.remove(inst);  
  },  
  
  // 通過Component.contextTypes過濾由上層組件注入的context屬性闺兢,僅保留Component.contextTypes約定的  
  _maskContext: function (context) {  
    var Component = this._currentElement.type;  
    var contextTypes = Component.contextTypes;  
    if (!contextTypes) {  
      return emptyObject;  
    }  
    var maskedContext = {};  
    for (var contextName in contextTypes) {  
      maskedContext[contextName] = context[contextName];  
    }  
    return maskedContext;  
  },  
  
  // 通過Component.contextTypes過濾由上層組件注入的context屬性茂缚,并做校驗(yàn)  
  _processContext: function (context) {  
    var maskedContext = this._maskContext(context);  
    if (process.env.NODE_ENV !== 'production') {  
      var Component = this._currentElement.type;  
      if (Component.contextTypes) {  
        this._checkContextTypes(Component.contextTypes, maskedContext, 'context');  
      }  
    }  
    return maskedContext;  
  },  
  
  // 將當(dāng)前組件的Context注入子組件;執(zhí)行g(shù)etChildContext方法并作校驗(yàn)屋谭,注入子組件的context中  
  _processChildContext: function (currentContext) {  
    var Component = this._currentElement.type;  
    var inst = this._instance;  
    var childContext;  
  
    if (inst.getChildContext) {  
      if (process.env.NODE_ENV !== 'production') {  
        ReactInstrumentation.debugTool.onBeginProcessingChildContext();  
        try {  
          childContext = inst.getChildContext();  
        } finally {  
          ReactInstrumentation.debugTool.onEndProcessingChildContext();  
        }  
      } else {  
        childContext = inst.getChildContext();  
      }  
    }  
  
    if (childContext) {  
      !(typeof Component.childContextTypes === 'object') ?   
        process.env.NODE_ENV !== 'production' ?   
          invariant(false, '%s.getChildContext(): '   
            + 'childContextTypes must be defined in order to use getChildContext().',   
            this.getName() || 'ReactCompositeComponent')   
          : _prodInvariant('107', this.getName() || 'ReactCompositeComponent')   
        : void 0;  
  
      if (process.env.NODE_ENV !== 'production') {  
        this._checkContextTypes(Component.childContextTypes, childContext, 'childContext');  
      }  
      for (var name in childContext) {  
        !(name in Component.childContextTypes) ?   
          process.env.NODE_ENV !== 'production' ?   
            invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.',   
              this.getName() || 'ReactCompositeComponent', name)   
            : _prodInvariant('108', this.getName() || 'ReactCompositeComponent', name)   
          : void 0;  
      }  
      return _assign({}, currentContext, childContext);  
    }  
    return currentContext;  
  },  
  
  // 校驗(yàn)context  
  _checkContextTypes: function (typeSpecs, values, location) {  
    if (process.env.NODE_ENV !== 'production') {  
      checkReactTypeSpec(typeSpecs, values, location, this.getName(), null, this._debugID);  
    }  
  },  
  
  // 接受新的組件待渲染元素nextElement脚囊,以替換舊的組件元素this._currentElement  
  // 通過performUpdateIfNecessary方法調(diào)用,nextElement由this._pendingElement提供  
  //    該方法觸發(fā)執(zhí)行的實(shí)際情形是ReactDom.render(ReactNode,pNode)掛載的組件元素桐磁,其父節(jié)點(diǎn)pNode由react方式繪制  
  // 通過_updateRenderedComponent方法調(diào)用悔耘,nextElement為待變更的子組件元素  
  receiveComponent: function (nextElement, transaction, nextContext) {  
    var prevElement = this._currentElement;  
    var prevContext = this._context;  
  
    this._pendingElement = null;  
  
    this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext);  
  },  
  
  // 由ReactDom.render(ReactNode,pNode)方法插入文檔時,pNode由react方式繪制  
  //    調(diào)用ReactReconciler.receiveComponent間接執(zhí)行updateComponent方法重繪組件  
  // 組件的setState我擂、replaceState衬以、forceUpdate方法觸發(fā)重繪缓艳,直接調(diào)用updateComponent方法重繪組件  
  performUpdateIfNecessary: function (transaction) {  
    // ReactDom.render方法渲染時包裹元素由react組件渲染,將待渲染元素推入_pendingElement中  
    if (this._pendingElement != null) {  
      ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context);  
  
    // 通過調(diào)用組件的setState看峻、replaceState阶淘、forceUpdate方法重繪組件  
    } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {  
      this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);  
      
    } else {  
      this._updateBatchNumber = null;  
    }  
  },  
  
  // 判斷props變更情況,執(zhí)行shouldComponentUpdate方法互妓,重繪組件或者更改組件的屬性  
  // 參數(shù)transaction溪窒,組件重繪時用于向子組件提供updater參數(shù),setState等方法可用冯勉;以及實(shí)現(xiàn)componentWillMount掛載功能  
  // 參數(shù)prevParentElement變更前的組件元素ReactNode澈蚌,nextParentElement變更后的組件元素,作為render方法渲染節(jié)點(diǎn)的父元素  
  // 參數(shù)prevUnmaskedContext更迭前的context灼狰,nextUnmaskedContext更迭后的context  
  updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {  
    var inst = this._instance;  
  
    // 組件實(shí)例尚未生成宛瞄,報錯  
    !(inst != null) ? process.env.NODE_ENV !== 'production' ?   
      invariant(false,   
        'Attempted to update component `%s` that has already been unmounted (or failed to mount).',   
        this.getName() || 'ReactCompositeComponent')   
      : _prodInvariant('136', this.getName() || 'ReactCompositeComponent')   
      : void 0;  
  
    var willReceive = false;  
    var nextContext;  
  
    // 更新context  
    if (this._context === nextUnmaskedContext) {  
      nextContext = inst.context;  
    } else {  
      nextContext = this._processContext(nextUnmaskedContext);  
      willReceive = true;  
    }  
  
    var prevProps = prevParentElement.props;  
    var nextProps = nextParentElement.props;  
  
    // 包含僅待渲染元素的props變更  
    if (prevParentElement !== nextParentElement) {  
      willReceive = true;  
    }  
  
    // 更新context、或變更帶渲染組件元素或其props時willReceive賦值為真交胚,由父組件發(fā)起份汗,調(diào)用componentWillReceiveProps方法  
    if (willReceive && inst.componentWillReceiveProps) {  
      if (process.env.NODE_ENV !== 'production') {  
        measureLifeCyclePerf(function () {  
          return inst.componentWillReceiveProps(nextProps, nextContext);  
        }, this._debugID, 'componentWillReceiveProps');  
      } else {  
        inst.componentWillReceiveProps(nextProps, nextContext);  
      }  
    }  
  
    // _processPendingState方法獲取組件setState、replaceState方法執(zhí)行后的最終state  
    var nextState = this._processPendingState(nextProps, nextContext);  
    var shouldUpdate = true;  
  
    // 調(diào)用組件的shouldComponentUpdate判斷是否需要重繪  
    // 純組件不能設(shè)置shouldComponentUpdate方法承绸,僅判斷props裸影、state是否變更  
    if (!this._pendingForceUpdate) {  
      if (inst.shouldComponentUpdate) {  
        if (process.env.NODE_ENV !== 'production') {  
          shouldUpdate = measureLifeCyclePerf(function () {  
            return inst.shouldComponentUpdate(nextProps, nextState, nextContext);  
          }, this._debugID, 'shouldComponentUpdate');  
        } else {  
          shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);  
        }  
      } else {  
        if (this._compositeType === CompositeTypes.PureClass) {  
          shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState);  
        }  
      }  
    }  
  
    // shouldComponentUpdate方法返回undefined,警告  
    if (process.env.NODE_ENV !== 'production') {  
      process.env.NODE_ENV !== 'production' ?   
        warning(shouldUpdate !== undefined,   
          '%s.shouldComponentUpdate(): Returned undefined instead of a '   
          + 'boolean value. Make sure to return true or false.',   
          this.getName() || 'ReactCompositeComponent')   
        : void 0;  
    }  
  
    this._updateBatchNumber = null;  
  
    // 重繪組件  
    if (shouldUpdate) {  
      this._pendingForceUpdate = false;  
  
      // 執(zhí)行componentWillUpdate方法军熏,重繪組件實(shí)例render方法內(nèi)待渲染的子組件,掛載componentDidUpdate方法  
      this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);  
      
    // 只變更組件的部分屬性卷扮,不開啟重繪功能  
    } else {  
      this._currentElement = nextParentElement;  
      this._context = nextUnmaskedContext;  
      inst.props = nextProps;  
      inst.state = nextState;  
      inst.context = nextContext;  
    }  
  },  
  
  // 獲取組件setState荡澎、replaceState方法執(zhí)行后的最終state  
  // setState、replaceState方法執(zhí)行后更迭的state以函數(shù)或state數(shù)據(jù)形式推入_pendingStateQueue中  
  _processPendingState: function (props, context) {  
    var inst = this._instance;  
    var queue = this._pendingStateQueue;  
    var replace = this._pendingReplaceState;  
    this._pendingReplaceState = false;  
    this._pendingStateQueue = null;  
  
    if (!queue) {  
      return inst.state;  
    }  
  
    if (replace && queue.length === 1) {  
      return queue[0];  
    }  
  
    var nextState = _assign({}, replace ? queue[0] : inst.state);  
    for (var i = replace ? 1 : 0; i < queue.length; i++) {  
      var partial = queue[i];  
      _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);  
    }  
  
    return nextState;  
  },  
  
  // 執(zhí)行componentWillUpdate方法晤锹,重繪組件實(shí)例render方法內(nèi)待渲染的子組件摩幔,掛載componentDidUpdate方法  
  _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {  
    var _this2 = this;  
  
    var inst = this._instance;  
  
    var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);  
    var prevProps;  
    var prevState;  
    var prevContext;  
    if (hasComponentDidUpdate) {  
      prevProps = inst.props;  
      prevState = inst.state;  
      prevContext = inst.context;  
    }  
  
    // 執(zhí)行componentWillUpdate方法  
    if (inst.componentWillUpdate) {  
      if (process.env.NODE_ENV !== 'production') {  
        measureLifeCyclePerf(function () {  
          return inst.componentWillUpdate(nextProps, nextState, nextContext);  
        }, this._debugID, 'componentWillUpdate');  
      } else {  
        inst.componentWillUpdate(nextProps, nextState, nextContext);  
      }  
    }  
  
    this._currentElement = nextElement;  
    this._context = unmaskedContext;  
    inst.props = nextProps;  
    inst.state = nextState;  
    inst.context = nextContext;  
  
    // 以更新子組件的方式或重新創(chuàng)建子組件的方式重繪render方法待渲染的子組件  
    this._updateRenderedComponent(transaction, unmaskedContext);  
  
    // 向后置鉤子transaction.getReactMountReady()中添加實(shí)例的生命周期方法componentDidUpdate  
    if (hasComponentDidUpdate) {  
      if (process.env.NODE_ENV !== 'production') {  
        transaction.getReactMountReady().enqueue(function () {  
          measureLifeCyclePerf(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), _this2._debugID, 'componentDidUpdate');  
        });  
      } else {  
        transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);  
      }  
    }  
  },  
  
  // 以更新子組件的方式或重新創(chuàng)建子組件的方式重繪render方法待渲染的子組件  
  _updateRenderedComponent: function (transaction, context) {  
    var prevComponentInstance = this._renderedComponent;// 組件render待渲染的子組件實(shí)例  
    var prevRenderedElement = prevComponentInstance._currentElement;// 子組件元素  
  
    // _renderValidatedComponent方法調(diào)用組件實(shí)例inst的render方法,獲取待掛載的元素  
    var nextRenderedElement = this._renderValidatedComponent();  
  
    var debugID = 0;  
    if (process.env.NODE_ENV !== 'production') {  
      debugID = this._debugID;  
    }  
  
    // shouldUpdateReactComponent方法返回真值鞭铆,更新組件實(shí)例或衡;返回否值,銷毀實(shí)例后车遂、重新創(chuàng)建實(shí)例  
    // 組件元素的構(gòu)造函數(shù)或key值不同封断,銷毀實(shí)例后再行創(chuàng)建  
  
    // render方法子組件構(gòu)造函數(shù)及key相同,通過ReactReconciler.receiveComponent方法更新子組件實(shí)例  
    if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {  
      ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));  
      
    // render方法子組件構(gòu)造函數(shù)或key不同舶担,重新創(chuàng)建子組件實(shí)例后坡疼,調(diào)用_replaceNodeWithMarkup方法替換掛載元素  
    } else {  
      var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);  
      ReactReconciler.unmountComponent(prevComponentInstance, false);  
  
      var nodeType = ReactNodeTypes.getType(nextRenderedElement);  
      this._renderedNodeType = nodeType;  
      var child = this._instantiateReactComponent(nextRenderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */  
      );  
      this._renderedComponent = child;  
  
      var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context), debugID);  
  
      if (process.env.NODE_ENV !== 'production') {  
        if (debugID !== 0) {  
          var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];  
          ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);  
        }  
      }  
  
      // 替換文檔中掛載的Dom元素DomLazyTree  
      this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance);  
    }  
  },  
  
  // 替換文檔中掛載的Dom元素DomLazyTree  
  _replaceNodeWithMarkup: function (oldHostNode, nextMarkup, prevInstance) {  
    ReactComponentEnvironment.replaceNodeWithMarkup(oldHostNode, nextMarkup, prevInstance);  
  },  
  
  // 調(diào)用組件實(shí)例inst的render方法,獲取待掛載的元素  
  _renderValidatedComponentWithoutOwnerOrContext: function () {  
    var inst = this._instance;  
    var renderedElement;  
  
    if (process.env.NODE_ENV !== 'production') {  
      renderedElement = measureLifeCyclePerf(function () {  
        return inst.render();  
      }, this._debugID, 'render');  
    } else {  
      renderedElement = inst.render();  
    }  
  
    if (process.env.NODE_ENV !== 'production') {  
      if (renderedElement === undefined && inst.render._isMockFunction) {  
        renderedElement = null;  
      }  
    }  
  
    return renderedElement;  
  },  
  
  // 調(diào)用組件實(shí)例inst的render方法衣陶,獲取待掛載的元素  
  _renderValidatedComponent: function () {  
    var renderedElement;  
    if (process.env.NODE_ENV !== 'production' || this._compositeType !== CompositeTypes.StatelessFunctional) {  
      ReactCurrentOwner.current = this;  
      try {  
        renderedElement = this._renderValidatedComponentWithoutOwnerOrContext();  
      } finally {  
        ReactCurrentOwner.current = null;  
      }  
    } else {  
      renderedElement = this._renderValidatedComponentWithoutOwnerOrContext();  
    }  
  
    // 校驗(yàn)renderedElement是否為ReactElement  
    !(renderedElement === null || renderedElement === false || React.isValidElement(renderedElement))   
      ? process.env.NODE_ENV !== 'production' ?   
        invariant(false, '%s.render(): A valid React element (or null) must be returned. '   
          + 'You may have returned undefined, an array or some other invalid object.',   
          this.getName() || 'ReactCompositeComponent')   
        : _prodInvariant('109', this.getName() || 'ReactCompositeComponent')   
      : void 0;  
  
    return renderedElement;  
  },  
  
  // 對外提供接口柄瑰,用于向組件實(shí)例ReactComponentInstance添加this.refs屬性  
  attachRef: function (ref, component) {// 參數(shù)component為子組件  
    var inst = this.getPublicInstance();  
  
    // 無狀態(tài)組件沒有this.refs屬性  
    !(inst != null) ? process.env.NODE_ENV !== 'production' ?   
      invariant(false, 'Stateless function components cannot have refs.')   
      : _prodInvariant('110') : void 0;  
  
    var publicComponentInstance = component.getPublicInstance();// 子組件的實(shí)例  
  
    // 無狀態(tài)子組件也不能作為上層組件的this.refs的值  
    if (process.env.NODE_ENV !== 'production') {  
      var componentName = component && component.getName ? component.getName() : 'a component';  
      process.env.NODE_ENV !== 'production' ?   
        warning(publicComponentInstance != null   
          || component._compositeType !== CompositeTypes.StatelessFunctional,   
          'Stateless function components cannot be given refs '   
          + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.',   
          ref, componentName, this.getName())   
        : void 0;  
    }  
  
    // 通過引用對象的形式賦值inst.refs  
    var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;  
    refs[ref] = publicComponentInstance;  
  },  
  
  // 銷毀組件實(shí)例ReactComponentInstance的refs屬性  
  detachRef: function (ref) {  
    var refs = this.getPublicInstance().refs;  
    delete refs[ref];  
  },  
  
  // 獲取組件名  
  getName: function () {  
    var type = this._currentElement.type;  
    var constructor = this._instance && this._instance.constructor;  
    return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null;  
  },  
  
  // 獲取組件ReactComponent的實(shí)例  
  getPublicInstance: function () {  
    var inst = this._instance;  
    if (this._compositeType === CompositeTypes.StatelessFunctional) {  
      return null;  
    }  
    return inst;  
  },  
  
  // 調(diào)用instantiateReactComponent模塊闸氮,用于創(chuàng)建子組件  
  _instantiateReactComponent: null  
  
};  
  
module.exports = ReactCompositeComponent;  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市教沾,隨后出現(xiàn)的幾起案子蒲跨,更是在濱河造成了極大的恐慌,老刑警劉巖授翻,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件财骨,死亡現(xiàn)場離奇詭異,居然都是意外死亡藏姐,警方通過查閱死者的電腦和手機(jī)隆箩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來羔杨,“玉大人捌臊,你說我怎么就攤上這事《挡模” “怎么了理澎?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長曙寡。 經(jīng)常有香客問我糠爬,道長,這世上最難降的妖魔是什么举庶? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任执隧,我火速辦了婚禮,結(jié)果婚禮上户侥,老公的妹妹穿的比我還像新娘镀琉。我一直安慰自己,他們只是感情好蕊唐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布屋摔。 她就那樣靜靜地躺著,像睡著了一般替梨。 火紅的嫁衣襯著肌膚如雪钓试。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天副瀑,我揣著相機(jī)與錄音弓熏,去河邊找鬼。 笑死俗扇,一個胖子當(dāng)著我的面吹牛硝烂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铜幽,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼滞谢,長吁一口氣:“原來是場噩夢啊……” “哼串稀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起狮杨,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤母截,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后橄教,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體清寇,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年护蝶,在試婚紗的時候發(fā)現(xiàn)自己被綠了华烟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡持灰,死狀恐怖盔夜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情堤魁,我是刑警寧澤喂链,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站妥泉,受9級特大地震影響椭微,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盲链,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一蝇率、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧匈仗,春花似錦瓢剿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽攻泼。三九已至火架,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間忙菠,已是汗流浹背何鸡。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牛欢,地道東北人骡男。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像傍睹,于是被迫代替她去往敵國和親隔盛。 傳聞我的和親對象是個殘疾皇子犹菱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評論 2 355