Use strings as the type for DOM elements

This makes ReactDOM a simple helper for creating ReactElements with the string tag as the type. The actual class is internal and created by instantiateReactComponent. Configurable using injection.

There's not a separate class for each tag. There's just a generic ReactDOMComponent which could take any tag name.

Invididual tags can be wrapped. When wrapping happens you can return the same tag again. If the wrapper returns the same string, then we fall back to the generic component. This avoids recursion in a single level wrapper.
This commit is contained in:
Sebastian Markbage
2014-10-02 23:05:11 -07:00
parent 35764c5ffb
commit 3aaccd2dc9
16 changed files with 328 additions and 215 deletions
+39 -5
View File
@@ -101,18 +101,51 @@ function putListener(id, registrationName, listener, transaction) {
);
}
// For HTML, certain tags should omit their close tag. We keep a whitelist for
// those special cased tags.
var omittedCloseTags = {
'area': true,
'base': true,
'br': true,
'col': true,
'embed': true,
'hr': true,
'img': true,
'input': true,
'keygen': true,
'link': true,
'meta': true,
'param': true,
'source': true,
'track': true,
'wbr': true
// NOTE: menuitem's close tag should be omitted, but that causes problems.
};
/**
* Creates a new React class that is idempotent and capable of containing other
* React components. It accepts event listeners and DOM properties that are
* valid according to `DOMProperty`.
*
* - Event listeners: `onClick`, `onMouseDown`, etc.
* - DOM properties: `className`, `name`, `title`, etc.
*
* The `style` property functions differently from the DOM API. It accepts an
* object mapping of style properties to values.
*
* @constructor ReactDOMComponent
* @extends ReactComponent
* @extends ReactMultiChild
*/
function ReactDOMComponent(tag, omitClose) {
this._tagOpen = '<' + tag;
this._tagClose = omitClose ? '' : '</' + tag + '>';
function ReactDOMComponent(tag) {
// TODO: DANGEROUS this tag should be sanitized.
this._tag = tag;
this.tagName = tag.toUpperCase();
}
ReactDOMComponent.displayName = 'ReactDOMComponent';
ReactDOMComponent.Mixin = {
/**
@@ -136,10 +169,11 @@ ReactDOMComponent.Mixin = {
mountDepth
);
assertValidProps(this.props);
var closeTag = omittedCloseTags[this._tag] ? '' : '</' + this._tag + '>';
return (
this._createOpenTagMarkupAndPutListeners(transaction) +
this._createContentMarkup(transaction) +
this._tagClose
closeTag
);
}
),
@@ -158,7 +192,7 @@ ReactDOMComponent.Mixin = {
*/
_createOpenTagMarkupAndPutListeners: function(transaction) {
var props = this.props;
var ret = this._tagOpen;
var ret = '<' + this._tag;
for (var propKey in props) {
if (!props.hasOwnProperty(propKey)) {