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 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);

        this._updateDOMProperties(null, this._currentElement.props);
        this._createInitialChildren(this._currentElement.props, domElement);

        FeactInstanceMap.set(domElement, this);
        this._hostNode = domElement;
        return domElement;
    }

    _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);
            }
        }
    }
}

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);
    }
}

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);
    },
};

function FeactComponent() {}

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);

    return markUp;
}

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

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

    getInitialState() {
        return {
            message: 'state from getInitialState',
            a: 0,
            b: 1,
        };
    },
    componentDidMount() {
        console.log('did mount');
    },
    componentWillReceiveProps(nextProps) {},

    render() {
        this.renderCount += 1;

        return Feact.createElement(
            'h1', {}, [
                'pure txt',
                Feact.createElement('div', {}, 'list item2', Feact.createElement('div', {}, 'list list item2')),
                Feact.createElement('div', {}, 'list item2', Feact.createElement('div', {}, 'list list item2')),
            ],
            null,
            Feact.createElement(
                'p',
                null,
                'this is render ' +
                this.renderCount +
                ', with state: ' +
                this.state.message +
                ', and this prop: ' +
                this.props.prop,
                Feact.createElement('p', {}, 'child-p-third')
            )
        );
    },
});

Feact.render(
    Feact.createElement(MyComponent, { prop: 'first prop' }, Feact.createElement('div', {}, 'fewroot')),
    document.getElementById('app')
);
<div id="app">
</div>