You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
4.1 KiB
125 lines
4.1 KiB
/** |
|
* Copyright 2014-2015, Facebook, Inc. |
|
* All rights reserved. |
|
* |
|
* This source code is licensed under the BSD-style license found in the |
|
* LICENSE file in the root directory of this source tree. An additional grant |
|
* of patent rights can be found in the PATENTS file in the same directory. |
|
* |
|
* @providesModule ReactChildReconciler |
|
* @typechecks static-only |
|
*/ |
|
|
|
'use strict'; |
|
|
|
var ReactReconciler = require("./ReactReconciler"); |
|
|
|
var flattenChildren = require("./flattenChildren"); |
|
var instantiateReactComponent = require("./instantiateReactComponent"); |
|
var shouldUpdateReactComponent = require("./shouldUpdateReactComponent"); |
|
|
|
/** |
|
* ReactChildReconciler provides helpers for initializing or updating a set of |
|
* children. Its output is suitable for passing it onto ReactMultiChild which |
|
* does diffed reordering and insertion. |
|
*/ |
|
var ReactChildReconciler = { |
|
|
|
/** |
|
* Generates a "mount image" for each of the supplied children. In the case |
|
* of `ReactDOMComponent`, a mount image is a string of markup. |
|
* |
|
* @param {?object} nestedChildNodes Nested child maps. |
|
* @return {?object} A set of child instances. |
|
* @internal |
|
*/ |
|
instantiateChildren: function(nestedChildNodes, transaction, context) { |
|
var children = flattenChildren(nestedChildNodes); |
|
for (var name in children) { |
|
if (children.hasOwnProperty(name)) { |
|
var child = children[name]; |
|
// The rendered children must be turned into instances as they're |
|
// mounted. |
|
var childInstance = instantiateReactComponent(child, null); |
|
children[name] = childInstance; |
|
} |
|
} |
|
return children; |
|
}, |
|
|
|
/** |
|
* Updates the rendered children and returns a new set of children. |
|
* |
|
* @param {?object} prevChildren Previously initialized set of children. |
|
* @param {?object} nextNestedChildNodes Nested child maps. |
|
* @param {ReactReconcileTransaction} transaction |
|
* @param {object} context |
|
* @return {?object} A new set of child instances. |
|
* @internal |
|
*/ |
|
updateChildren: function( |
|
prevChildren, |
|
nextNestedChildNodes, |
|
transaction, |
|
context) { |
|
// We currently don't have a way to track moves here but if we use iterators |
|
// instead of for..in we can zip the iterators and check if an item has |
|
// moved. |
|
// TODO: If nothing has changed, return the prevChildren object so that we |
|
// can quickly bailout if nothing has changed. |
|
var nextChildren = flattenChildren(nextNestedChildNodes); |
|
if (!nextChildren && !prevChildren) { |
|
return null; |
|
} |
|
var name; |
|
for (name in nextChildren) { |
|
if (!nextChildren.hasOwnProperty(name)) { |
|
continue; |
|
} |
|
var prevChild = prevChildren && prevChildren[name]; |
|
var prevElement = prevChild && prevChild._currentElement; |
|
var nextElement = nextChildren[name]; |
|
if (shouldUpdateReactComponent(prevElement, nextElement)) { |
|
ReactReconciler.receiveComponent( |
|
prevChild, nextElement, transaction, context |
|
); |
|
nextChildren[name] = prevChild; |
|
} else { |
|
if (prevChild) { |
|
ReactReconciler.unmountComponent(prevChild, name); |
|
} |
|
// The child must be instantiated before it's mounted. |
|
var nextChildInstance = instantiateReactComponent( |
|
nextElement, |
|
null |
|
); |
|
nextChildren[name] = nextChildInstance; |
|
} |
|
} |
|
// Unmount children that are no longer present. |
|
for (name in prevChildren) { |
|
if (prevChildren.hasOwnProperty(name) && |
|
!(nextChildren && nextChildren.hasOwnProperty(name))) { |
|
ReactReconciler.unmountComponent(prevChildren[name]); |
|
} |
|
} |
|
return nextChildren; |
|
}, |
|
|
|
/** |
|
* Unmounts all rendered children. This should be used to clean up children |
|
* when this component is unmounted. |
|
* |
|
* @param {?object} renderedChildren Previously initialized set of children. |
|
* @internal |
|
*/ |
|
unmountChildren: function(renderedChildren) { |
|
for (var name in renderedChildren) { |
|
var renderedChild = renderedChildren[name]; |
|
ReactReconciler.unmountComponent(renderedChild); |
|
} |
|
} |
|
|
|
}; |
|
|
|
module.exports = ReactChildReconciler;
|
|
|