Created
September 30, 2016 02:29
-
-
Save LiuuY/f7b77b2cf317fd90d2789af3e50c1dfa to your computer and use it in GitHub Desktop.
Naïve React (no updates 😛) in 60 lines https://twitter.com/dan_abramov/status/781620845185732608
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width"> | |
<title>JS Bin</title> | |
</head> | |
<body> | |
<div id="root"></div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://twitter.com/dan_abramov/status/781620845185732608 | |
// http://jsbin.com/qiguyibolu/1/edit?html,js,output | |
function isClass(type) { | |
// React.Component subclasses have this flag | |
return type.prototype && Boolean(type.prototype.isReactComponent); | |
} | |
function mountComposite(element) { | |
var type = element.type; | |
var props = element.props; | |
var renderedElement; | |
if (isClass(type)) { | |
// Component class | |
var instance = new type(props); | |
instance.componentWillMount(); | |
renderedElement = instance.render(); | |
} else if (typeof type === 'function') { | |
// Component function | |
renderedElement = type(props); | |
} | |
// Mount the rendered output | |
return mount(renderedElement); | |
} | |
function mountHost(element) { | |
var type = element.type; | |
var props = element.props; | |
var children = props.children; | |
// This block of code shouldn't be in the reconciler. | |
// Different renderers might initialize nodes differently. | |
// For example, React Native would create iOS or Android views. | |
var node = document.createElement(type); | |
Object.keys(props).forEach(propName => { | |
if (propName !== 'children') { | |
node.setAttribute(propName, props[propName]); | |
} | |
}); | |
// Mount the children | |
children.filter(Boolean).forEach(childElement => { | |
var childNode = mount(childElement); | |
// This line of code is also renderer-specific. | |
// It would be different depending on the renderer: | |
node.appendChild(childNode); | |
}); | |
// Return the DOM node as mount result | |
return node; | |
} | |
function mount(element) { | |
var type = element.type; | |
if (typeof type === 'function') { | |
// User-defined components | |
return mountComposite(element); | |
} else if (typeof type === 'string') { | |
// Platform-specific components | |
return mountHost(element); | |
} | |
} | |
// ---------------------------- | |
// Necessary for JSX to work | |
window.React = { | |
createElement(type, props, ...children) { | |
return { | |
type, | |
props: { | |
...props, | |
children: children || props.children | |
} | |
} | |
} | |
}; | |
function Button() { | |
return <div class="button" />; | |
} | |
function App() { | |
return ( | |
<div> | |
<Button /> | |
<Button /> | |
<Button /> | |
</div> | |
); | |
} | |
var rootEl = document.getElementById('root'); | |
var node = mount(<App />); | |
rootEl.appendChild(node); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment