SOURCE

console 命令行工具 X clear

                    
>
console
const FeactInstanceMap = {
    set(key, value) {
        key.__feactInternalInstance = value;
    },

    get(key) {
        return key.__feactInternalInstance;
    },
};

function flatten(list, depth) {
    depth = typeof depth == 'number' ? depth : Infinity;

    if (!depth) {
        if (Array.isArray(list)) {
            return list.map(function(i) {
                return i;
            });
        }
        return list;
    }

    return _flatten(list, 1);

    function _flatten(list, d) {
        return list.reduce(function(acc, item) {
            //if(d>1)item
            if (Array.isArray(item) && d < depth) {
                return acc.concat(_flatten(item, d + 1));
            } else {
                return acc.concat(item);
            }
        }, []);
    }
}

function shouldUpdateFeactComponent(prevElement, nextElement) {
    if (prevElement != null && nextElement != null) {
        var prevType = typeof prevElement;
        var nextType = typeof nextElement;
        if (prevType === 'string' || prevType === 'number') {
            return nextType === 'string' || nextType === 'number';
        } else {
            return (
                nextType === 'object' && prevElement.type === nextElement.type && prevElement.key === nextElement.key
            );
        }
    }
    return false;
}

function flattenChildren(children, init_value) {
    let childrenMap = {};
    init_value = init_value || '';
    for (let i = 0; i < children.length; i++) {
        let child = children[i];
        let name = `.${i}`;
        if (Array.isArray(child)) {
            let flattendObject = flattenChildren(child, `.${i}`);
            Object.assign(childrenMap, flattendObject);
            continue;
        }

        if (child && child._currentElement && child._currentElement.key) {
            //实例
            name = `.$${child._currentElement.key}`;
        }

        if (child && child.key) {
            name = `.$${child.key}`;
        }
        name = init_value + name;
        childrenMap[name] = child;
    }
    return childrenMap;
}
class FeactEmptyComponent {
    constructor(text) {
        this._currentElement = text;
        this._stringText = '' + text;
        this._domNode = null;
        this._hostParent = null;
        this._hostContainerInfo = null;
    }
    mountComponent(hostParent, hostContainerInfo) {
        this._hostParent = hostParent;
        this._hostContainerInfo = hostContainerInfo;
        this._domNode = document.createComment('feact --- empty --- component');
        return this._domNode;
    }
    getHost() {
        return this._domNode;
    }
    receiveComponent() {}
}
class FeactDOMTextComponent {
    constructor(text) {
        this._currentElement = text;
        this._stringText = '' + text;
        this._domNode = null;
        this._hostParent = null;
        this._hostContainerInfo = null;
    }
    mountComponent(hostParent, hostContainerInfo) {
        this._hostParent = hostParent;
        this._hostContainerInfo = hostContainerInfo;
        this._domNode = document.createTextNode(this._currentElement);
        return this._domNode;
    }
    getHost() {
        return this._domNode;
    }
    receiveComponent(txt) {
        //if (this._currentElement == txt) return;
        this._domNode.data = txt;
    }
}

function instantiateFeactComponentArrayItem(ele) {
    if (Array.isArray(ele)) {
        return ele.map((item, index) => {
            return instantiateFeactComponent(item);
        });
    } else return instantiateFeactComponent(ele);
}
//全局的更新深度标识
var updateDepth = 0;
//全局的更新队列,所有的差异都存在这里
var diffQueue = [];

var globalIdCounter = 1;
class FeactDOMComponent {
    constructor(element) {
        this._currentElement = element;
        this._renderedChildren = null;
        this._hostNode = null;
        this._hostParent = null;
        this._rootNodeID = 0;
        this._domID = 0;
        this._hostContainerInfo = null;
        this._wrapperState = null;
        this._topLevelWrapper = null;
    }
    getHost() {
        return this._hostNode;
    }
    mountChildren(propschildren, el) {
        //得到propschildren 对应的实例 一级children todo
        //   var children = FeactReconciler.instantiateChildren(this, propschildren);
        var mountImages = [];
        var index = 0;
        var children = [];
        let flattenpropschildren = propschildren;
        for (let i = 0; i < flattenpropschildren.length; i++) {
            let child = flattenpropschildren[i];
            let vInstance = instantiateFeactComponentArrayItem(child);
            children.push(vInstance);
        }
        let flattenddChildrenInst = flatten(children);
        for (let j = 0; j < flattenddChildrenInst.length; j++) {
            let vInstance = flattenddChildrenInst[j];
            vInstance._mountIndex = j;
            mountImages.push(FeactReconciler.mountComponent(vInstance, this));
        }

        this._renderedChildren = flattenChildren(children);
        return mountImages;
    }
    _createInitialChildren(props, el) {
        var mountImages = this.mountChildren(props.children, el);
        for (var i = 0; i < mountImages.length; i++) {
            el.appendChild(mountImages[i]);
        }
    }
    mountComponent(hostParent, hostContainerInfo) {
        this._hostParent = hostParent;
        this._rootNodeID = globalIdCounter++;
        this._domID = hostContainerInfo && hostContainerInfo._idCounter++;
        const domElement = document.createElement(this._currentElement.type);
        //const textNode = document.createTextNode(this._currentElement.props.children);
        this._updateDOMProperties(null, this._currentElement.props);
        this._createInitialChildren(this._currentElement.props, domElement);

        // domElement.appendChild(textNode);
        //container.appendChild(domElement);
        FeactInstanceMap.set(domElement, this);
        this._hostNode = domElement;
        return domElement;
    }

    receiveComponent(nextElement) {
        const prevElement = this._currentElement;
        this.updateComponent(prevElement, nextElement);
    }

    updateComponent(prevElement, nextElement) {
        const lastProps = prevElement.props;
        const nextProps = nextElement.props;

        this._updateDOMProperties(lastProps, nextProps);
        this._updateDOMChildren(lastProps, nextProps);
    }

    updateChildren(prevChildren, nextChildrenE, diffQueue) {
        let hostNode = this._hostNode;
        //1.先把 扁平化
        let ob = {};
        /*
            _reconcilerUpdateChildren 部分
        */
        var nextChildren = {};
        let nextChildrenElements = flattenChildren(nextChildrenE);
        var mountImages = [];
        var removedNodes = {};

        for (let name in nextChildrenElements) {
            let prevChild = prevChildren && prevChildren[name];
            var prevElement = prevChild && prevChild._currentElement;
            var nextElement = nextChildrenElements[name];
            if (prevChild != null && shouldUpdateFeactComponent(prevElement, nextElement)) {
                //把diff交给下面
                FeactReconciler.receiveComponent(prevChild, nextElement);
                nextChildren[name] = prevChild;
                // console.log(name);
            } else {
                var nextChildInstance = instantiateFeactComponent(nextElement);
                nextChildren[name] = nextChildInstance;
                // Creating mount image now ensures refs are resolved in right order
                // (see https://github.com/facebook/react/pull/7101 for explanation).
                var nextChildMountImage = FeactReconciler.mountComponent(nextChildInstance, this);
                mountImages.push(nextChildMountImage);
                if (prevChild) {
                    prevChild._instance && prevChild._instance.componentWillUnmount && prevChild._instance.componentWillUnmount();
                    removedNodes[name] = prevChild.getHost();
                }
            }
        }
        // Unmount children that are no longer present.
        for (let name in prevChildren) {
            if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) {
                let prevChild = prevChildren[name];
                removedNodes[name] = prevChild.getHost();
            }
        }

        var lastIndex = 0; //代表访问的最后一次的老的集合的位置
        var nextMountIndex = 0;
        var nextIndex = 0; //代表到达的新的节点的index
        //  var diffQueue = [];
        //做diff
        var lastPlaceNode = null;
        debugger;
        for (let name in nextChildren) {
            let prevChild = prevChildren[name];
            let nextChild = nextChildren[name];
            if (prevChild == nextChild) {
                //move
                //存在两个相同的节点:进行移动
                prevChild._mountIndex < lastIndex &&
                    diffQueue.push({
                        parentNode: hostNode,
                        type: 'MOVE_EXISTING',
                        fromIndex: prevChild._mountIndex,
                        toIndex: nextIndex,
                        node: prevChild.getHost(),
                        afterNode: lastPlaceNode,
                    });
                lastIndex = Math.max(prevChild._mountIndex, lastIndex);
            } else {
                //不存在两个相同的节点
                if (prevChild) {
                    //这种情况是,比如key相同,但是具体的内部实例已经不同了
                    //要移除原先的内部实例
                    lastIndex = Math.max(prevChild._mountIndex, lastIndex);
                    // The `removedNodes` loop below will actually remove the child.
                }
                diffQueue.push({
                    parentNode: hostNode,
                    type: 'INSERT_NODE',
                    fromIndex: null,
                    toIndex: nextIndex,
                    markup: mountImages[nextMountIndex++],
                    afterNode: lastPlaceNode,
                });
            }
            nextChild._mountIndex = nextIndex;
            nextIndex++;
            lastPlaceNode = nextChild.getHost();
        }

        for (let name in removedNodes) {
            if (removedNodes.hasOwnProperty(name)) {
                diffQueue.push({
                    parentNode: hostNode,
                    type: 'DELETE_NODE',
                    fromIndex: prevChildren[name]._mountIndex,
                    toIndex: null,
                    node: removedNodes[name],
                });
                //updates = enqueue(updates, this._unmountChild(prevChildren[name], removedNodes[name]));
            }
        }

        this._renderedChildren = nextChildren;
    }
    _updateDOMProperties(lastProps, nextProps) {
        // nothing to do! I'll explain why below
        let eventReg = /^on[\w]*$/;
        for (let propskey in nextProps) {
            if (propskey.match(eventReg)) {
                let eventHanlder = nextProps[propskey];
                ReactEventEmitter.putListener(this._rootNodeID, propskey, eventHanlder);
            }
        }
    }

    _updateDOMChildren(lastProps, nextProps) {
        let hostNode = this._hostNode;
        const lastContent = lastProps.children;
        const nextContent = nextProps.children;
        let diffQueue = [];
        // updateDepth++;
        //_diff用来递归找出差别,组装差异对象,添加到更新队列diffQueue。
        this.updateChildren(this._renderedChildren, nextProps.children, diffQueue);
        //updateDepth--;
        //if (updateDepth == 0) {
        //在需要的时候调用patch,执行具体的dom操作
        this._patch(diffQueue);
        //}
    }
    _patch(updates) {
        console.log(updates);
        var initialChildren = {};
        var deleteChildren = [];

        for (var k = 0; k < updates.length; k++) {
            let update = updates[k];
            switch (update.type) {
                case 'INSERT_NODE':
                    insertChildAt(update.parentNode, update.markup, getNodeAfter(update.parentNode, update.afterNode));
                    //  insertChildAt(update.parentNode, update.markup, update.toIndex);
                    break;
                case 'MOVE_EXISTING':
                    insertChildAt(update.parentNode, update.node, getNodeAfter(update.parentNode, update.afterNode));

                    break;
                case 'DELETE_NODE':
                    // update.parentNode.removeChild(update.node);
                    update.node.remove();
                    break;
            }
        }
    }
    updateTextContent(content) {
        const node = this._hostNode;
        node.textContent = content;

        const firstChild = node.firstChild;

        if (firstChild && firstChild === node.lastChild && firstChild.nodeType === 3) {
            firstChild.nodeValue = content;
            return;
        }

        node.textContent = content;
    }
}
var ReactEventEmitter = {
    listenerBank: {},

    putListener: function putListener(id, registrationName, listener) {
        var bankForRegistrationName = this.listenerBank[registrationName] || (this.listenerBank[registrationName] = {});

        bankForRegistrationName[id] = listener;
    },

    getListener: function getListener(id, registrationName) {
        return this.listenerBank[registrationName][id];
    },

    trapBubbledEvent: function trapBubbledEvent(topLevelEventType, element) {
        var eventMap = {
            onClick: 'click',
        };
        var baseEventType = eventMap[topLevelEventType];
        element.addEventListener(baseEventType, this.dispatchEvent.bind(this, topLevelEventType));
    },

    dispatchEvent: function dispatchEvent(eventType, event) {
        //这个是原生事件
        event.preventDefault();
        let internalInst = FeactInstanceMap.get(event.target);
        //    var id = internalInst._rootNodeID;
        //先默认实现一个bubbule的事件系统
        var parentArray = [];
        var listenArray = [];
        var parent = internalInst;
        while (parent) {
            parentArray.push(parent);
            parent = parent._hostParent;
        }
        for (let i = 0; i < parentArray.length; i++) {
            let instID = parentArray[i]._rootNodeID;
            let handler = this.getListener(instID, eventType);
            handler && listenArray.push(handler);
        }
        for (let i = 0; i < listenArray.length; i++) {
            listenArray[i](event);
        }
        //var listener = this.getListener(id, eventType);
        //if (listener) {
        //  listener(event);
        //}
    },
};

function insertChildAt(parentNode, childNode, index) {
    if (typeof index != 'number') {
        parentNode.insertBefore(childNode, index);
        return;
    }
    var beforeChild = parentNode.childNodes[index];
    beforeChild ? parentNode.insertBefore(childNode, beforeChild) : parentNode.append(childNode);
}
class FeactCompositeComponentWrapper {
    //自定义组件virtual  node
    constructor(element) {
        this._currentElement = element;
        this._rootNodeID = 0;
        this._compositeType = null;
        this._instance = null;
        this._hostParent = null;
        this._hostContainerInfo = null;
    }
    getHost() {
        return this._renderedComponent.getHost();
    }
    mountComponent(hostParent, hostContainerInfo) {
        this._hostParent = hostParent;
        this._hostContainerInfo = hostContainerInfo;
        const Component = this._currentElement.type;
        //这个type拿到一个函数 这个函数有那些对应的 react 方法
        const componentInstance = new Component(this._currentElement.props);
        //componentInstance 这个实例不是react vnode 的实例 是React.component的实例
        this._instance = componentInstance;

        FeactInstanceMap.set(componentInstance, this);

        if (componentInstance.componentWillMount) {
            componentInstance.componentWillMount();
        }

        const markup = this.performInitialMount();

        if (componentInstance.componentDidMount) {
            componentInstance.componentDidMount();
        }

        return markup;
    }

    performInitialMount() {
        //调用自定义组件的render方法,其实就是调用creactElement 出来的
        const renderedElement = this._instance.render();

        //virtual node 工厂得到child 可能会多个不同的实例 公用一组接口
        const child = instantiateFeactComponent(renderedElement);
        this._renderedComponent = child;

        //在这里抹平了mountComponent的过程
        //child.mountComponent 可能是FeactDOMComponent.mountComponent
        //也可能是FeactCompositeComponentWrapper.mountComponent
        return FeactReconciler.mountComponent(child, this);
    }

    performUpdateIfNecessary() {
        //应该是为事务做准备的 perform
        //两个一样的强制不走componentWillReceiveProps
        this.updateComponent(this._currentElement, this._currentElement);
    }

    receiveComponent(nextElement) {
        const prevElement = this._currentElement;
        this.updateComponent(prevElement, nextElement);
    }

    updateComponent(prevElement, nextElement) {
        //更新组件
        this._updating = true;
        const nextProps = nextElement.props;
        const inst = this._instance;

        const willReceive = prevElement !== nextElement;

        if (willReceive && inst.componentWillReceiveProps) {
            inst.componentWillReceiveProps(nextProps);
        }

        let shouldUpdate = true;

        const nextState = this._processPendingState();

        if (inst.shouldComponentUpdate) {
            shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState);
        }

        if (shouldUpdate) {
            this._performComponentUpdate(nextElement, nextProps, nextState);
        } else {
            inst.props = nextProps;
        }

        this._updating = false;
    }
    unmountComponent() {
        const inst = this._instance;
        inst.componentWillUnmount && inst.componentWillUnmount();
    }
    _processPendingState() {
        const inst = this._instance;
        if (!this._pendingPartialState) {
            return inst.state;
        }

        let nextState = inst.state;

        for (let i = 0; i < this._pendingPartialState.length; ++i) {
            nextState = Object.assign({}, nextState, this._pendingPartialState[i]);
        }

        this._pendingPartialState = null;
        return nextState;
    }

    _performComponentUpdate(nextElement, nextProps, nextState) {
        this._currentElement = nextElement;
        //Component为真正React.Component
        const inst = this._instance;
        var hasComponentDidUpdate = !!inst.componentDidUpdate;
        var prevProps;
        var prevState;
        if (hasComponentDidUpdate) {
            prevProps = inst.props;
            prevState = inst.state;
        }
        //真正更新状态
        inst.props = nextProps;
        inst.state = nextState;
        inst.componentWillUpdate && inst.componentWillUpdate(nextProps, nextState);
        this._updateRenderedComponent();
        inst.componentDidUpdate && inst.componentDidUpdate(prevProps, prevState);
    }

    _updateRenderedComponent() {
        const prevComponentInstance = this._renderedComponent;
        const inst = this._instance;
        const prevRenderedElement = prevComponentInstance._currentElement;
        //接受新props 和 state的时候再次render
        const nextRenderedElement = inst.render();

        /*
            todo nextRenderedElement prevComponentInstance
            判断key然后根据判断结果进行receiveComponent 还是instant 再 mount
        */

        //渲染过的_renderedComponent接受新的render得到的element
        //这个地方也会出现分叉,可能是FeactDOMComponent.receiveComponent
        //也可能是FeactCompositeComponentWrapper.receiveComponent
        if (shouldUpdateFeactComponent(prevRenderedElement, nextRenderedElement)) {
            FeactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement);
        } else {
            var oldHostNode = prevComponentInstance.getHost();
            //var nodeType = ReactNodeTypes.getType(nextRenderedElement);
            //this._renderedNodeType = nodeType;
            var child = instantiateFeactComponent(nextRenderedElement);

            this._renderedComponent = child;

            var nextMarkup = FeactReconciler.mountComponent(child, this);

            let parent = oldHostNode.parentElement;

            parent.innerHTML = '';
            parent.append(nextMarkup);

            FeactReconciler.unmountComponent(prevComponentInstance);
        }
    }
}

const TopLevelWrapper = function(props) {
    this.props = props;
};

TopLevelWrapper.prototype.render = function() {
    return this.props;
};

function instantiateFeactComponent(element) {
    //virtuan node 工厂
    if (element == null || element == undefined) {
        return new FeactEmptyComponent(element);
    } else if (typeof element === 'string') {
        return new FeactDOMTextComponent(element);
    } else if (typeof element.type === 'string') {
        return new FeactDOMComponent(element);
    } else if (typeof element.type === 'function') {
        return new FeactCompositeComponentWrapper(element);
    }
}

const FeactReconciler = {
    mountComponent(internalInstance, parentNode, hostContainerInfo) {
        return internalInstance.mountComponent(parentNode, hostContainerInfo);
    },

    receiveComponent(internalInstance, nextElement) {
        internalInstance.receiveComponent(nextElement);
    },

    performUpdateIfNecessary(internalInstance) {
        internalInstance.performUpdateIfNecessary();
    },
    instantiateChildren(internalInstance, propschildren) {
        internalInstance.instantiateChildren(propschildren);
    },
    unmountComponent(internalInstance) {
        internalInstance.unmountComponent && internalInstance.unmountComponent();
    }
};

function FeactComponent() {}

FeactComponent.prototype.setState = function(partialState) {
    //在全局map中根据React.Component实例取出对应的内部的virtul node Component 实例
    const internalInstance = FeactInstanceMap.get(this);
    internalInstance._pendingPartialState = internalInstance._pendingPartialState || [];
    internalInstance._pendingPartialState.push(partialState);

    //todo batchupdate
    if (!internalInstance._updating) {
        //防止每次setState都触发更新
        FeactReconciler.performUpdateIfNecessary(internalInstance);
    }
};

function mixSpecIntoComponent(Constructor, spec) {
    const proto = Constructor.prototype;

    for (const key in spec) {
        proto[key] = spec[key];
    }
}

//createElement 建立了一个什么?
const Feact = {
    createElement(type, props, ...children) {
        const element = {
            type,
            props: props || {},
        };

        if (props && props.key) {
            element.key = props.key;
        }
        if (children) {
            element.props.children = children;
        }
        //返回一个对象,但是真实react不是这样?
        //返回一个element,代表虚拟Object
        return element;
    },
    //creactClass利用FeactComponent(Component)混入成 Component
    createClass(spec) {
        function Constructor(props) {
            this.props = props;
            const initialState = this.getInitialState ? this.getInitialState() : null;
            //this为FeactComponent(React.Component)实例
            this.state = initialState;
        }

        Constructor.prototype = new FeactComponent();

        mixSpecIntoComponent(Constructor, spec);

        return Constructor;
    },
    //React.render
    render(element, container) {
        //获得保存过的实例
        const prevComponent = getTopLevelComponentInContainer(container);

        if (prevComponent) {
            //container挂载过
            return updateRootComponent(prevComponent, element);
        } else {
            //render 返回真实dom
            return renderNewRootComponent(element, container);
        }
    },
};

function getTopLevelComponentInContainer(container) {
    return container.__feactComponentInstance;
}

function renderNewRootComponent(element, container) {
    //新建dom 挂载在container
    //type是一个function
    const wrapperElement = Feact.createElement(TopLevelWrapper, element);
    //new了 一个 vCompositeNode
    const componentInstance = new FeactCompositeComponentWrapper(wrapperElement);

    const markUp = FeactReconciler.mountComponent(componentInstance, null);
    // container.__feactComponentInstance 挂了 vCompositeNode 的render返回的vCompositeNode
    container.__feactComponentInstance = componentInstance._renderedComponent;
    container.appendChild(markUp);
    ReactEventEmitter.trapBubbledEvent('onClick', document);
    return markUp;
}

function updateRootComponent(prevComponent, nextElement) {
    FeactReconciler.receiveComponent(prevComponent, nextElement);
}

const MyComponent = Feact.createClass({
    componentWillMount() {
        this.renderCount = 0;
    },

    getInitialState() {
        return {
            message: 'state from getInitialState',
        };
    },

    componentWillReceiveProps(nextProps) {
        console.log('will reiceive');
    },

    render() {
        this.renderCount += 1;
        return Feact.createElement(
            'h1',
            null,
            'this is render ' +
            this.renderCount +
            ', with state: ' +
            this.state.message +
            ', and this prop: ' +
            this.props.a +
            'a::::' +
            this.props.a,
            ...this.props.children
        );
    },
});

function getNodeAfter(parentNode, node) {
    // Special case for text components, which return [open, close] comments
    // from getHostNode.
    if (Array.isArray(node)) {
        node = node[1];
    }
    return node ? node.nextSibling : parentNode.firstChild;
}
const MyComponent123 = Feact.createClass({
    componentWillMount() {
        this.renderCount = 0;
    },

    getInitialState() {
        return {
            message: 'state from getInitialState',
            a: 0,
            b: 1,
        };
    },
    componentDidMount() {
        setTimeout(() => {
            this.setState({
                message: 'frrffrfr',
                a: 1,
                b: 0,
            });
        }, 3000);
    },
    componentWillReceiveProps(nextProps) {
        //  this.setState({ message: 'state from componentWillReceiveProps' });
    },
    onClickBubble(e) {
        console.log('事件冒泡了');
    },
    changeState(v, e) {
        this.setState({
            a: v,
        });
    },
    render() {
        this.renderCount += 1;
        // if (this.state.a == 1) {
        // return Feact.createElement(
        //     'h1',
        //     null,
        //     'this is render ' +
        //     this.renderCount +
        //     ', with state: ' +
        //     this.state.message +
        //     ', and this prop: ' +
        //     this.props.prop,
        //     Feact.createElement('h2', {}, 'root-third')
        // );
        // }
        return Feact.createElement(
            'h1', {
                onClick: this.onClickBubble.bind(this),
            }, [
                'pure txt',
                this.state.a ?
                Feact.createElement('div', { key: this.state.a ? 'f' : 'd' }, 'list item1') :
                Feact.createElement(
                    'div', { key: this.state.a ? 'd' : 'f' },
                    'list item2',
                    Feact.createElement('div', {}, 'list list item2')
                ),
                this.state.a ?
                Feact.createElement(
                    'div', { key: this.state.a ? 'd' : 'f' },
                    'list item2',
                    Feact.createElement('div', {}, 'list list item2')
                ) :
                Feact.createElement('div', { key: this.state.a ? 'f' : 'd' }, 'list item1'),
            ],

            this.state.a ?
            Feact.createElement(
                'h2', {
                    onClick: this.onClickBubble.bind(this),
                },
                'ttt'
            ) :
            null,
            this.state.a ?
            Feact.createElement(
                'p',
                null,
                'this is render ' +
                this.renderCount +
                ', with state: ' +
                this.state.message +
                ', and this prop: ' +
                this.props.prop,
                Feact.createElement('p', {}, 'p-third')
            ) :
            Feact.createElement('section', {}, null),
            Feact.createElement('button', { onClick: this.changeState.bind(this, 0) }, '恢复状态'),
            Feact.createElement('button', { onClick: this.changeState.bind(this, 1) }, '设置状态'),

            // this.state.a ? Feact.createElement('h2', {}, 'yyy') : null,
            //Feact.createElement('div', { key: this.state.a ? '1' : '111' }, 'root-second')
        );
    },
});

Feact.render(
    Feact.createElement(MyComponent123, { prop: 'first prop' }, Feact.createElement('div', {}, 'fewroot')),
    document.getElementById('app')
);

// setTimeout(function() {
//     Feact.render(Feact.createElement(MyComponent, { prop: 'second prop' }), document.getElementById('root'));
// }, 2000);
<div id="app"></div>