其實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