13
13
14
14
var DOMChildrenOperations = require ( 'DOMChildrenOperations' ) ;
15
15
var DOMLazyTree = require ( 'DOMLazyTree' ) ;
16
- var DOMPropertyOperations = require ( 'DOMPropertyOperations' ) ;
17
16
var ReactDOMComponentTree = require ( 'ReactDOMComponentTree' ) ;
18
17
var ReactPerf = require ( 'ReactPerf' ) ;
19
18
20
19
var assign = require ( 'Object.assign' ) ;
21
20
var escapeTextContentForBrowser = require ( 'escapeTextContentForBrowser' ) ;
22
21
var validateDOMNesting = require ( 'validateDOMNesting' ) ;
23
22
24
- var getNode = ReactDOMComponentTree . getNodeFromInstance ;
25
-
26
23
/**
27
24
* Text nodes violate a couple assumptions that React makes about components:
28
25
*
29
26
* - When mounting text into the DOM, adjacent text nodes are merged.
30
27
* - Text nodes cannot be assigned a React root ID.
31
28
*
32
- * This component is used to wrap strings in elements so that they can undergo
33
- * the same reconciliation that is applied to elements.
29
+ * This component is used to wrap strings between comment nodes so that they
30
+ * can undergo the same reconciliation that is applied to elements.
34
31
*
35
32
* TODO: Investigate representing React components in the DOM with text nodes.
36
33
*
@@ -49,6 +46,8 @@ var ReactDOMTextComponent = function(text) {
49
46
// Properties
50
47
this . _domID = null ;
51
48
this . _mountIndex = 0 ;
49
+ this . _openingComment = null ;
50
+ this . _commentNodes = null ;
52
51
} ;
53
52
54
53
assign ( ReactDOMTextComponent . prototype , {
@@ -77,34 +76,44 @@ assign(ReactDOMTextComponent.prototype, {
77
76
if ( parentInfo ) {
78
77
// parentInfo should always be present except for the top-level
79
78
// component when server rendering
80
- validateDOMNesting ( 'span ' , this , parentInfo ) ;
79
+ validateDOMNesting ( '#text ' , this , parentInfo ) ;
81
80
}
82
81
}
83
82
84
83
var domID = nativeContainerInfo . _idCounter ++ ;
84
+ var openingValue = ' react-text: ' + domID + ' ' ;
85
+ var closingValue = ' /react-text ' ;
85
86
this . _domID = domID ;
86
87
this . _nativeParent = nativeParent ;
87
88
if ( transaction . useCreateElement ) {
88
89
var ownerDocument = nativeContainerInfo . _ownerDocument ;
89
- var el = ownerDocument . createElement ( 'span' ) ;
90
- ReactDOMComponentTree . precacheNode ( this , el ) ;
91
- var lazyTree = DOMLazyTree ( el ) ;
92
- DOMLazyTree . queueText ( lazyTree , this . _stringText ) ;
90
+ var openingComment = ownerDocument . createComment ( openingValue ) ;
91
+ var closingComment = ownerDocument . createComment ( closingValue ) ;
92
+ var lazyTree = DOMLazyTree ( ownerDocument . createDocumentFragment ( ) ) ;
93
+ DOMLazyTree . queueChild ( lazyTree , DOMLazyTree ( openingComment ) ) ;
94
+ if ( this . _stringText ) {
95
+ DOMLazyTree . queueChild (
96
+ lazyTree ,
97
+ DOMLazyTree ( ownerDocument . createTextNode ( this . _stringText ) )
98
+ ) ;
99
+ }
100
+ DOMLazyTree . queueChild ( lazyTree , DOMLazyTree ( closingComment ) ) ;
101
+ this . _openingComment = openingComment ;
102
+ ReactDOMComponentTree . precacheNode ( this , closingComment ) ;
93
103
return lazyTree ;
94
104
} else {
95
105
var escapedText = escapeTextContentForBrowser ( this . _stringText ) ;
96
106
97
107
if ( transaction . renderToStaticMarkup ) {
98
- // Normally we'd wrap this in a `span` for the reasons stated above, but
99
- // since this is a situation where React won't take over (static pages),
100
- // we can simply return the text as it is.
108
+ // Normally we'd wrap this between comment nodes for the reasons stated
109
+ // above, but since this is a situation where React won't take over
110
+ // (static pages), we can simply return the text as it is.
101
111
return escapedText ;
102
112
}
103
113
104
114
return (
105
- '<span ' + DOMPropertyOperations . createMarkupForID ( domID ) + '>' +
106
- escapedText +
107
- '</span>'
115
+ '<!--' + openingValue + '-->' + escapedText +
116
+ '<!--' + closingValue + '-->'
108
117
) ;
109
118
}
110
119
} ,
@@ -125,16 +134,29 @@ assign(ReactDOMTextComponent.prototype, {
125
134
// and/or updateComponent to do the actual update for consistency with
126
135
// other component types?
127
136
this . _stringText = nextStringText ;
128
- DOMChildrenOperations . updateTextContent ( getNode ( this ) , nextStringText ) ;
137
+ var commentNodes = this . getNativeNode ( ) ;
138
+ DOMChildrenOperations . replaceDelimitedText (
139
+ commentNodes [ 0 ] ,
140
+ commentNodes [ 1 ] ,
141
+ nextStringText
142
+ ) ;
129
143
}
130
144
}
131
145
} ,
132
146
133
147
getNativeNode : function ( ) {
134
- return getNode ( this ) ;
148
+ var nativeNode = this . _commentNodes ;
149
+ if ( nativeNode ) {
150
+ return nativeNode ;
151
+ }
152
+ nativeNode = [ this . _openingComment , this . _nativeNode ] ;
153
+ this . _commentNodes = nativeNode ;
154
+ return nativeNode ;
135
155
} ,
136
156
137
157
unmountComponent : function ( ) {
158
+ this . _openingComment = null ;
159
+ this . _commentNodes = null ;
138
160
ReactDOMComponentTree . uncacheNode ( this ) ;
139
161
} ,
140
162
0 commit comments