其实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行,
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转义了,转义后的代码是:
'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)。
在ReactDOM.render的时候,Clock这个function对象,1、有了父类React.Component,在被调用的时候,如果自己定义了构造器,那么使用自己的,没有的话使用父类的构造器。2、原型上有自己定义的方法。
而3、createElement的第二个参数这里虽然是null,但是如果传递的属性的话,是一个对象。到此为止,创建一个虚拟节点(普通节点+组件两种,这里主要讨论组件)的所有要素:一个构造方法(以便生成一个对象来保存组件的内部变量)+所有的组件对象都继承同一个父类(Vue里是所有的组件都是VueComponent的实例,继承的是Vue这个父类,这里父类是React.Component,子类自己写)+传递给组件的属性