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