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 (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) {
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) {
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) {
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 {
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;
const componentInstance = new Component(this._currentElement.props);
this._instance = componentInstance;
FeactInstanceMap.set(componentInstance, this);
if (componentInstance.componentWillMount) {
componentInstance.componentWillMount();
}
const markup = this.performInitialMount();
if (componentInstance.componentDidMount) {
componentInstance.componentDidMount();
}
return markup;
}
performInitialMount() {
const renderedElement = this._instance.render();
const child = instantiateFeactComponent(renderedElement);
this._renderedComponent = child;
return FeactReconciler.mountComponent(child, this);
}
}
const TopLevelWrapper = function(props) {
this.props = props;
};
TopLevelWrapper.prototype.render = function() {
return this.props;
};
function instantiateFeactComponent(element) {
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];
}
}
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;
}
return element;
},
createClass(spec) {
function Constructor(props) {
this.props = props;
const initialState = this.getInitialState ? this.getInitialState() : null;
this.state = initialState;
}
Constructor.prototype = new FeactComponent();
mixSpecIntoComponent(Constructor, spec);
return Constructor;
},
render(element, container) {
const prevComponent = getTopLevelComponentInContainer(container);
if (prevComponent) {
return updateRootComponent(prevComponent, element);
} else {
return renderNewRootComponent(element, container);
}
},
};
function getTopLevelComponentInContainer(container) {
return container.__feactComponentInstance;
}
function renderNewRootComponent(element, container) {
const wrapperElement = Feact.createElement(TopLevelWrapper, element);
const componentInstance = new FeactCompositeComponentWrapper(wrapperElement);
const markUp = FeactReconciler.mountComponent(componentInstance, null);
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>