React源碼之 從開始提及

其實react和vue思想差很少,render生成虛擬節點,對比改變真實節點響應。

 

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!--<script src="./react.development.js"></script>-->
    <!--<script src="./react-dom.development.js"></script>-->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>

<div id="example"></div>
<script type="text/babel">
    class Clock extends React.Component {
        render() {
            return (
                <div><h1></h1>
                </div>
            );
        }
    }
    ReactDOM.render(
        <Clock></Clock>,
        document.getElementById('example')
    );
</script>

</body>
</html>

 

好比上面的代碼,ReactDOM來自react-dom.development.js的11746行,render方法在17771行,javascript

render: function (element, container, callback) {
            return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
        },

  參數裏的container就是example這個div Node,element的話比較複雜:在js裏寫<Clock>這樣的語法並不報錯是由於<script type="text/babel">這裏,jsx語法通過babel轉義了,轉義後的代碼是:html

'use strict';

var _createClass = function() {
    function defineProperties(target, props) {
        for (var i = 0; i < props.length; i++) {
            var descriptor = props[i];
            descriptor.enumerable = descriptor.enumerable || false;
            descriptor.configurable = true;
            if ("value"in descriptor)
                descriptor.writable = true;
            Object.defineProperty(target, descriptor.key, descriptor);
        }
    }
    return function(Constructor, protoProps, staticProps) {
        if (protoProps)
            defineProperties(Constructor.prototype, protoProps);
        if (staticProps)
            defineProperties(Constructor, staticProps);
        return Constructor;
    }
    ;
}();

function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
    }
}

function _possibleConstructorReturn(self, call) {
    if (!self) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
    return call && (typeof call === "object" || typeof call === "function") ? call : self;
}

function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
    if (superClass)
        Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

var Clock = function(_React$Component) {
    _inherits(Clock, _React$Component);

    function Clock() {
        _classCallCheck(this, Clock);

        return _possibleConstructorReturn(this, (Clock.__proto__ || Object.getPrototypeOf(Clock)).apply(this, arguments));
    }

    _createClass(Clock, [{
        key: 'render',
        value: function render() {
            return React.createElement('div', null, '123');
        }
    }]);

    return Clock;
}(React.Component);

ReactDOM.render(React.createElement(Clock, null), document.getElementById('example'));

上面邏輯不復雜,就是一些繼承驗證的東西,能夠看出element參數實際上是React.createElement(Clock, null)。vue

在ReactDOM.render的時候,Clock這個function對象,一、有了父類React.Component,在被調用的時候,若是本身定義了構造器,那麼使用本身的,沒有的話使用父類的構造器。二、原型上有本身定義的方法。java

而三、createElement的第二個參數這裏雖然是null,可是若是傳遞的屬性的話,是一個對象。到此爲止,建立一個虛擬節點(普通節點+組件兩種,這裏主要討論組件)的全部要素:一個構造方法(以便生成一個對象來保存組件的內部變量)+全部的組件對象都繼承同一個父類(Vue裏是全部的組件都是VueComponent的實例,繼承的是Vue這個父類,這裏父類是React.Component,子類本身寫)+傳遞給組件的屬性react

相關文章
相關標籤/搜索