Browse Source

update zh-docs14.3 ,fixed confliction

main
iamchenxin 9 years ago
parent
commit
a206ab1a22
  1. 2
      _config.yml
  2. 2
      _js/html-jsx.js
  3. 2
      _posts/2014-10-16-react-v0.12-rc1.md
  4. 2
      _posts/2014-11-24-react-js-conf-updates.md
  5. 37
      _posts/2015-12-29-react-v0.14.4.md
  6. 60
      _posts/2016-01-08-A-implies-B-does-not-imply-B-implies-A.md
  7. 10
      _posts/2016-01-12-discontinuing-ie8-support.md
  8. 2
      docs/03-interactivity-and-dynamic-uis.md
  9. 2
      docs/07-forms.md
  10. 45
      docs/08-working-with-the-browser.md
  11. 12
      docs/08.1-more-about-refs.md
  12. 1
      docs/10.4-test-utils.md
  13. 11
      docs/getting-started.md
  14. 4
      docs/ref-01-top-level-api.md
  15. 5
      docs/ref-03-component-specs.md
  16. 61
      docs/ref-04-tags-and-attributes.md
  17. 3
      docs/ref-05-events.md
  18. 2
      docs/ref-08-reconciliation.md
  19. 6
      docs/thinking-in-react.it-IT.md
  20. 6
      docs/thinking-in-react.ko-KR.md
  21. 6
      docs/thinking-in-react.md
  22. 116
      docs/thinking-in-react.zh-CN.md
  23. BIN
      downloads/react-0.14.4.zip
  24. BIN
      downloads/react-0.14.5.zip
  25. BIN
      downloads/react-0.14.6.zip
  26. BIN
      img/docs/should-component-update.png
  27. 2
      js/react-dom.js
  28. 44
      js/react.js
  29. 6
      tips/10-props-in-getInitialState-as-anti-pattern.md
  30. 2
      tips/18-use-react-with-other-libraries.ko-KR.md
  31. 2
      tips/18-use-react-with-other-libraries.md

2
_config.yml

@ -36,4 +36,4 @@ sass:
sass_dir: _css
gems:
- jekyll-redirect-from
react_version: 0.14.3
react_version: 0.14.6

2
_js/html-jsx.js

@ -1,5 +1,5 @@
/**
* Copyright 2013-2015, Facebook, Inc.
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the

2
_posts/2014-10-16-react-v0.12-rc1.md

@ -41,7 +41,7 @@ We have wanted to do this since before we even open sourced React. No more `/**
The React specific JSX transform no longer transforms to function calls. Instead we use `React.createElement` and pass it arguments. This allows us to make optimizations and better support React as a compile target for things like Om. Read more in the [React Elements introduction](/react/blog/2014/10/14/introducting-react-elements.html).
The result of this change is that we will no longer support arbitrary function calls. We understand that the ability to do was was a convenient shortcut for many people but we believe the gains will be worth it.
The result of this change is that we will no longer support arbitrary function calls. We understand that the ability to do was a convenient shortcut for many people but we believe the gains will be worth it.
### JSX Lower-case Convention

2
_posts/2014-11-24-react-js-conf-updates.md

@ -17,7 +17,7 @@ stick with the originally planned format and venue on Facebook's campus.
Unfortunately, this means that we can only accept a small number of the awesome
conference talk proposals. In order to make sure attendees get a fair shot at
registering, we're going to to sell tickets in three separate first-come,
registering, we're going to sell tickets in three separate first-come,
first-serve phases. **Tickets will cost $200 regardless of which phase they are
purchased from and all proceeds will go to charity**.

37
_posts/2015-12-29-react-v0.14.4.md

@ -0,0 +1,37 @@
---
title: "React v0.14.4"
author: spicyj
---
Happy December! We have a minor point release today. It has just a few small bug fixes.
The release is now available for download:
* **React**
Dev build with warnings: <https://fb.me/react-0.14.4.js>
Minified build for production: <https://fb.me/react-0.14.4.min.js>
* **React with Add-Ons**
Dev build with warnings: <https://fb.me/react-with-addons-0.14.4.js>
Minified build for production: <https://fb.me/react-with-addons-0.14.4.min.js>
* **React DOM** (include React in the page before React DOM)
Dev build with warnings: <https://fb.me/react-dom-0.14.4.js>
Minified build for production: <https://fb.me/react-dom-0.14.4.min.js>
* **React DOM Server** (include React in the page before React DOM Server)
Dev build with warnings: <https://fb.me/react-dom-server-0.14.4.js>
Minified build for production: <https://fb.me/react-dom-server-0.14.4.min.js>
We've also published version `0.14.4` of the `react`, `react-dom`, and addons packages on npm and the `react` package on bower.
- - -
## Changelog
### React
- Minor internal changes for better compatibility with React Native
### React DOM
- The `autoCapitalize` and `autoCorrect` props are now set as attributes in the DOM instead of properties to improve cross-browser compatibility
- Fixed bug with controlled `<select>` elements not handling updates properly
### React Perf Add-on
- Some DOM operation names have been updated for clarity in the output of `.printDOM()`

60
_posts/2016-01-08-A-implies-B-does-not-imply-B-implies-A.md

@ -0,0 +1,60 @@
---
title: "(A => B) !=> (B => A)"
author: jimfb
---
The documentation for `componentWillReceiveProps` states that `componentWillReceiveProps` will be invoked when the props change as the result of a rerender. Some people assume this means "if `componentWillReceiveProps` is called, then the props must have changed", but that conclusion is logically incorrect.
The guiding principle is one of my favorites from formal logic/mathematics:
> A implies B does not imply B implies A
Example: "If I eat moldy food, then I will get sick" does not imply "if I am sick, then I must have eaten moldy food". There are many other reasons I could be feeling sick. For instance, maybe the flu is circulating around the office. Similarly, there are many reasons that `componentWillReceiveProps` might get called, even if the props didn’t change.
If you don’t believe me, call `ReactDOM.render()` three times with the exact same props, and try to predict the number of times `componentWillReceiveProps` will get called:
```js
class Component extends React.Component {
componentWillReceiveProps(nextProps) {
console.log('componentWillReceiveProps', nextProps.data.bar);
}
render() {
return <div>Bar {this.props.data.bar}!</div>;
}
}
var container = document.getElementById('container');
var mydata = {bar: 'drinks'};
ReactDOM.render(<Component data={mydata} />, container);
ReactDOM.render(<Component data={mydata} />, container);
ReactDOM.render(<Component data={mydata} />, container);
```
In this case, the answer is "2". React calls `componentWillReceiveProps` twice (once for each of the two updates). Both times, the value of "drinks" is printed (ie. the props didn’t change).
To understand why, we need to think about what *could* have happened. The data *could* have changed between the initial render and the two subsequent updates, if the code had performed a mutation like this:
```js
var mydata = {bar: 'drinks'};
ReactDOM.render(<Component data={mydata} />, container);
mydata.bar = 'food'
ReactDOM.render(<Component data={mydata} />, container);
mydata.bar = 'noise'
ReactDOM.render(<Component data={mydata} />, container);
```
React has no way of knowing that the data didn’t change. Therefore, React needs to call `componentWillReceiveProps`, because the component needs to be notified of the new props (even if the new props happen to be the same as the old props).
You might think that React could just use smarter checks for equality, but there are some issues with this idea:
* The old `mydata` and the new `mydata` are actually the same physical object (only the object’s internal value changed). Since the references are triple-equals-equal, doing an equality check doesn’t tell us if the value has changed. The only possible solution would be to have created a deep copy of the data, and then later do a deep comparison - but this can be prohibitively expensive for large data structures (especially ones with cycles).
* The `mydata` object might contain references to functions which have captured variables within closures. There is no way for React to peek into these closures, and thus no way for React to copy them and/or verify equality.
* The `mydata` object might contain references to objects which are re-instantiated during the parent's render (ie. not triple-equals-equal) but are conceptually equal (ie. same keys and same values). A deep-compare (expensive) could detect this, except that functions present a problem again because there is no reliable way to compare two functions to see if they are semantically equivalent.
Given the language constraints, it is sometimes impossible for us to achieve meaningful equality semantics. In such cases, React will call `componentWillReceiveProps` (even though the props might not have changed) so the component has an opportunity to examine the new props and act accordingly.
As a result, your implementation of `componentWillReceiveProps` MUST NOT assume that your props have changed. If you want an operation (such as a network request) to occur only when props have changed, your `componentWillReceiveProps` code needs to check to see if the props actually changed.

10
_posts/2016-01-12-discontinuing-ie8-support.md

@ -0,0 +1,10 @@
---
title: "Discontinuing IE 8 Support in React DOM"
author: spicyj
---
Since its 2013 release, React has supported all popular browsers, including Internet Explorer 8 and above. We handle normalizing many quirks present in old browser versions, including event system differences, so that your app code doesn't have to worry about most browser bugs.
Today, Microsoft [discontinued support for older versions of IE](https://www.microsoft.com/en-us/WindowsForBusiness/End-of-IE-support). Starting with React v15, we're discontinuing React DOM's support for IE 8. We've heard that most React DOM apps already don't support old versions of Internet Explorer, so this shouldn't affect many people. This change will help us develop faster and make React DOM even better. (We won't actively remove IE 8–related code quite yet, but we will deprioritize new bugs that are reported. If you need to support IE 8 we recommend you stay on React v0.14.)
React DOM will continue to support IE 9 and above for the foreseeable future.

2
docs/03-interactivity-and-dynamic-uis.md

@ -36,7 +36,7 @@ ReactDOM.render(
## Event Handling and Synthetic Events
With React you simply pass your event handler as a camelCased prop similar to how you'd do it in normal HTML. React ensures that all events behave identically in IE8 and above by implementing a synthetic event system. That is, React knows how to bubble and capture events according to the spec, and the events passed to your event handler are guaranteed to be consistent with [the W3C spec](http://www.w3.org/TR/DOM-Level-3-Events/), regardless of which browser you're using.
With React you simply pass your event handler as a camelCased prop similar to how you'd do it in normal HTML. React ensures that all events behave similarly in all browsers by implementing a synthetic event system. That is, React knows how to bubble and capture events according to the spec, and the events passed to your event handler are guaranteed to be consistent with [the W3C spec](http://www.w3.org/TR/DOM-Level-3-Events/), regardless of which browser you're using.
## Under the Hood: Autobinding and Event Delegation

2
docs/07-forms.md

@ -95,7 +95,7 @@ If you want to initialize the component with a non-empty value, you can supply a
This example will function much like the **Uncontrolled Components** example above.
Likewise, `<input>` supports `defaultChecked` and `<select>` supports `defaultValue`.
Likewise, `<input type="checkbox">` and `<input type="radio">` support `defaultChecked`, and `<select>` supports `defaultValue`.
> Note:
>

45
docs/08-working-with-the-browser.md

@ -12,7 +12,7 @@ React provides powerful abstractions that free you from touching the DOM directl
React is very fast because it never talks to the DOM directly. React maintains a fast in-memory representation of the DOM. `render()` methods actually return a *description* of the DOM, and React can compare this description with the in-memory representation to compute the fastest way to update the browser.
Additionally, React implements a full synthetic event system such that all event objects are guaranteed to conform to the W3C spec despite browser quirks, and everything bubbles consistently and efficiently across browsers. You can even use some HTML5 events in IE8!
Additionally, React implements a full synthetic event system such that all event objects are guaranteed to conform to the W3C spec despite browser quirks, and everything bubbles consistently and efficiently across browsers. You can even use some HTML5 events in older browsers that don't ordinarily support them!
Most of the time you should stay within React's "faked browser" world since it's more performant and easier to reason about. However, sometimes you simply need to access the underlying API, perhaps to work with a third-party library like a jQuery plugin. React provides escape hatches for you to use the underlying DOM API directly.
@ -53,45 +53,8 @@ _Mounted_ composite components also support the following method:
* `component.forceUpdate()` can be invoked on any mounted component when you know that some deeper aspect of the component's state has changed without using `this.setState()`.
## Browser Support and Polyfills
## Browser Support
At Facebook, we support older browsers, including IE8. We've had polyfills in place for a long time to allow us to write forward-thinking JS. This means we don't have a bunch of hacks scattered throughout our codebase and we can still expect our code to "just work". For example, instead of seeing `+new Date()`, we can just write `Date.now()`. Since the open source React is the same as what we use internally, we've carried over this philosophy of using forward thinking JS.
React supports most popular browsers, including Internet Explorer 9 and above.
In addition to that philosophy, we've also taken the stance that we, as authors of a JS library, should not be shipping polyfills as a part of our library. If every library did this, there's a good chance you'd be sending down the same polyfill multiple times, which could be a sizable chunk of dead code. If your product needs to support older browsers, chances are you're already using something like [es5-shim](https://github.com/es-shims/es5-shim).
### Polyfills Needed to Support Older Browsers
`es5-shim.js` from [kriskowal's es5-shim](https://github.com/es-shims/es5-shim) provides the following that React needs:
* `Array.isArray`
* `Array.prototype.every`
* `Array.prototype.forEach`
* `Array.prototype.indexOf`
* `Array.prototype.map`
* `Date.now`
* `Function.prototype.bind`
* `Object.keys`
* `String.prototype.split`
* `String.prototype.trim`
`es5-sham.js`, also from [kriskowal's es5-shim](https://github.com/es-shims/es5-shim), provides the following that React needs:
* `Object.create`
* `Object.freeze`
The unminified build of React needs the following from [paulmillr's console-polyfill](https://github.com/paulmillr/console-polyfill).
* `console.*`
When using HTML5 elements in IE8 including `<section>`, `<article>`, `<nav>`, `<header>`, and `<footer>`, it's also necessary to include [html5shiv](https://github.com/aFarkas/html5shiv) or a similar script.
### Cross-browser Issues
Although React is pretty good at abstracting browser differences, some browsers are limited or present quirky behaviors that we couldn't find a workaround for.
#### onScroll event on IE8
On IE8 the `onScroll` event doesn't bubble and IE8 doesn't have an API to define handlers to the capturing phase of an event, meaning there is no way for React to listen to these events.
Currently a handler to this event is ignored on IE8.
See the [onScroll doesn't work in IE8](https://github.com/facebook/react/issues/631) GitHub issue for more information.
(We don't support older browsers that don't support ES5 methods, but you may find that your apps do work in older browsers if polyfills such as [es5-shim and es5-sham](https://github.com/es-shims/es5-shim) are included in the page. You're on your own if you choose to take this path.)

12
docs/08.1-more-about-refs.md

@ -91,11 +91,13 @@ In order to get a reference to a React component, you can either use `this` to g
var MyComponent = React.createClass({
handleClick: function() {
// Explicitly focus the text input using the raw DOM API.
this.myTextInput.focus();
if (this.myTextInput !== null) {
this.myTextInput.focus();
}
},
render: function() {
// The ref attribute adds a reference to the component to
// this.refs when the component is mounted.
// The ref attribute is a callback that saves a reference to the
// component to this.myTextInput when the component is mounted.
return (
<div>
<input type="text" ref={(ref) => this.myTextInput = ref} />
@ -131,7 +133,7 @@ Refs are a great way to send a message to a particular child instance in a way t
### Cautions:
- *Never* access refs inside of any component's render method - or while any component's render method is even running anywhere in the call stack.
- *Never* access refs inside of any component's render method or while any component's render method is even running anywhere in the call stack.
- If you want to preserve Google Closure Compiler advanced-mode crushing resilience, make sure to never access as a property what was specified as a string. This means you must access using `this.refs['myRefString']` if your ref was defined as `ref="myRefString"`.
- If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where `state` should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use `ref`s to "make things happen" – instead, the data flow will usually accomplish your goal.
- If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use `ref`s to "make things happen" – instead, the data flow will usually accomplish your goal.
- Refs may not be attached to a [stateless function](/react/docs/reusable-components.html#stateless-functions), because the component does not have a backing instance. You can always wrap a stateless component in a standard composite component and attach a ref to the composite component.

1
docs/10.4-test-utils.md

@ -232,6 +232,7 @@ After `render` has been called, returns shallowly rendered output. You can then
Then you can assert:
```javascript
var renderer = ReactTestUtils.createRenderer();
result = renderer.getRenderOutput();
expect(result.type).toBe('div');
expect(result.props.children).toEqual([

11
docs/getting-started.md

@ -34,7 +34,7 @@ $ npm install --save react react-dom babelify babel-preset-react
$ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
```
To install React DOM and build your bundle with webpack:
To install React DOM and build your bundle with webpack:
```sh
$ npm install --save react react-dom babel-preset-react
@ -45,6 +45,15 @@ $ webpack
>
> If you are using ES2015, you will want to also use the `babel-preset-es2015` package.
**Note:** by default, React will be in development mode, which is slower, and not advised for production. To use React in production mode, set the environment variable `NODE_ENV` to `production` (using envify or webpack's DefinePlugin). For example:
```js
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify("production")
}
});
```
## Quick Start Without npm

4
docs/ref-01-top-level-api.md

@ -66,9 +66,7 @@ factoryFunction createFactory(
)
```
Return a function that produces ReactElements of a given type. Like `React.createElement`,
the type argument can be either an html tag name string (eg. 'div', 'span', etc), or a
`ReactClass`.
Return a function that produces ReactElements of a given type. Like `React.createElement`, the type argument can be either an html tag name string (eg. 'div', 'span', etc), or a `ReactClass`.
### React.isValidElement

5
docs/ref-03-component-specs.md

@ -148,6 +148,8 @@ componentWillReceiveProps: function(nextProps) {
> Note:
>
> One common mistake is for code executed during this lifecycle method to assume that props have changed. To understand why this is invalid, read [A implies B does not imply B implies A](/react/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html)
>
> There is no analogous method `componentWillReceiveState`. An incoming prop transition may cause a state change, but the opposite is not true. If you need to perform operations in response to a state change, use `componentWillUpdate`.
@ -161,8 +163,7 @@ boolean shouldComponentUpdate(
Invoked before rendering when new props or state are being received. This method is not called for the initial render or when `forceUpdate` is used.
Use this as an opportunity to `return false` when you're certain that the
transition to the new props and state will not require a component update.
Use this as an opportunity to `return false` when you're certain that the transition to the new props and state will not require a component update.
```javascript
shouldComponentUpdate: function(nextProps, nextState) {

61
docs/ref-04-tags-and-attributes.md

@ -18,11 +18,11 @@ The following HTML elements are supported:
a abbr address area article aside audio b base bdi bdo big blockquote body br
button canvas caption cite code col colgroup data datalist dd del details dfn
dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
h6 head header hr html i iframe img input ins kbd keygen label legend li link
main map mark menu menuitem meta meter nav noscript object ol optgroup option
output p param picture pre progress q rp rt ruby s samp script section select
small source span strong style sub summary sup table tbody td textarea tfoot th
thead time title tr track u ul var video wbr
h6 head header hgroup hr html i iframe img input ins kbd keygen label legend li
link main map mark menu menuitem meta meter nav noscript object ol optgroup
option output p param picture pre progress q rp rt ruby s samp script section
select small source span strong style sub summary sup table tbody td textarea
tfoot th thead time title tr track u ul var video wbr
```
### SVG elements
@ -30,11 +30,11 @@ thead time title tr track u ul var video wbr
The following SVG elements are supported:
```
circle clipPath defs ellipse g line linearGradient mask path pattern polygon polyline
radialGradient rect stop svg text tspan
circle clipPath defs ellipse g image line linearGradient mask path pattern
polygon polyline radialGradient rect stop svg text tspan
```
You may also be interested in [react-art](https://github.com/facebook/react-art), a drawing library for React that can render to Canvas, SVG, or VML (for IE8).
You may also be interested in [react-art](https://github.com/facebook/react-art), a cross-browser drawing library for React.
## Supported Attributes
@ -53,24 +53,32 @@ These standard attributes are supported:
```
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
async autoComplete autoFocus autoPlay capture cellPadding cellSpacing charSet
challenge checked classID className cols colSpan content contentEditable contextMenu
controls coords crossOrigin data dateTime defer dir disabled download draggable
encType form formAction formEncType formMethod formNoValidate formTarget frameBorder
headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode
keyParams keyType label lang list loop low manifest marginHeight marginWidth max
maxLength media mediaGroup method min minLength multiple muted name noValidate open
optimum pattern placeholder poster preload radioGroup readOnly rel required role
rows rowSpan sandbox scope scoped scrolling seamless selected shape size sizes
span spellCheck src srcDoc srcSet start step style summary tabIndex target title
type useMap value width wmode wrap
async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
charSet checked classID className colSpan cols content contentEditable
contextMenu controls coords crossOrigin data dateTime default defer dir
disabled download draggable encType form formAction formEncType formMethod
formNoValidate formTarget frameBorder headers height hidden high href hrefLang
htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
lang list loop low manifest marginHeight marginWidth max maxLength media
mediaGroup method min minLength multiple muted name noValidate nonce open
optimum pattern placeholder poster preload radioGroup readOnly rel required
reversed role rowSpan rows sandbox scope scoped scrolling seamless selected
shape size sizes span spellCheck src srcDoc srcLang srcSet start step style
summary tabIndex target title type useMap value width wmode wrap
```
These RDFa attributes are supported (several RDFa attributes overlap with standard HTML attributes and thus are excluded from this list):
```
about datatype inlist prefix property resource typeof vocab
```
In addition, the following non-standard attributes are supported:
- `autoCapitalize autoCorrect` for Mobile Safari.
- `property` for [Open Graph](http://ogp.me/) meta tags.
- `color` for `<link rel="mask-icon" />` in Safari.
- `itemProp itemScope itemType itemRef itemID` for [HTML5 microdata](http://schema.org/docs/gs.html).
- `security` for older versions of Internet Explorer.
- `unselectable` for Internet Explorer.
- `results autoSave` for WebKit/Blink input fields of type `search`.
@ -78,13 +86,6 @@ There is also the React-specific attribute `dangerouslySetInnerHTML` ([more here
### SVG Attributes
```
clipPath cx cy d dx dy fill fillOpacity fontFamily
fontSize fx fy gradientTransform gradientUnits markerEnd
markerMid markerStart offset opacity patternContentUnits
patternUnits points preserveAspectRatio r rx ry spreadMethod
stopColor stopOpacity stroke strokeDasharray strokeLinecap
strokeOpacity strokeWidth textAnchor transform version
viewBox x1 x2 x xlinkActuate xlinkArcrole xlinkHref xlinkRole
xlinkShow xlinkTitle xlinkType xmlBase xmlLang xmlSpace y1 y2 y
```
Any attributes passed to SVG tags are passed through without changes.
React used to support special camelCase aliases for certain SVG attributes, such as `clipPath`. If you use them now you'll see a deprecation warning. These aliases will be removed in the next version in favor of their real names from the SVG specification, such as `clip-path`. Attributes that have a camelCase name in the spec, such as `gradientTransform`, will keep their names.

3
docs/ref-05-events.md

@ -61,8 +61,7 @@ function onClick(event) {
## Supported Events
React normalizes events so that they have consistent properties across
different browsers.
React normalizes events so that they have consistent properties across different browsers.
The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append `Capture` to the event name; for example, instead of using `onClick`, you would use `onClickCapture` to handle the click event in the capture phase.

2
docs/ref-08-reconciliation.md

@ -13,7 +13,7 @@ React's key design decision is to make the API seem like it re-renders the whole
Generating the minimum number of operations to transform one tree into another is a complex and well-studied problem. The [state of the art algorithms](http://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf) have a complexity in the order of O(n<sup>3</sup>) where n is the number of nodes in the tree.
This means that displaying 1000 nodes would require in the order of one billion comparisons. This is far too expensive for our use case. To put this number in perspective, CPUs nowadays execute roughly 3 billion instruction per second. So even with the most performant implementation, we wouldn't be able to compute that diff in less than a second.
This means that displaying 1000 nodes would require in the order of one billion comparisons. This is far too expensive for our use case. To put this number in perspective, CPUs nowadays execute roughly 3 billion instructions per second. So even with the most performant implementation, we wouldn't be able to compute that diff in less than a second.
Since an optimal algorithm is not tractable, we implement a non-optimal O(n) algorithm using heuristics based on two assumptions:

6
docs/thinking-in-react.it-IT.md

@ -61,7 +61,7 @@ Adesso che abbiamo identificato i componenti nel nostro mock, organizziamoli in
## Passo 2: Costruisci una versione statica in React
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/yun1vgqb/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/yun1vgqb/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
Adesso che hai la tua gerarchia di componenti, è venuto il momento di implementare la tua applicazione. La maniera più semplice è costruire una versione che prende il tuo modello di dati e visualizza la UI ma non è interattiva. È buona norma disaccoppiare questi processi perché costruire una versione statica richiede la scrittura di parecchio codice e poco pensare, mentre aggiungere l'interattività richiede un parecchio pensare ma non un granché di scrittura. Vedremo perché.
@ -105,7 +105,7 @@ Quindi, per concludere, il nostro stato è:
## Passo 4: Identifica dove debba risiedere il tuo stato
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/zafjbw1e/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/zafjbw1e/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
OK, abbiamo dunque identificato quale sia l'insieme minimo dello stato dell'applicazione. Successivamente, dobbiamo identificare quale componente muta, o *possiede*, questo stato.
@ -130,7 +130,7 @@ Puoi cominciare a vedere come si comporterà la tua applicazione: imposta `filte
## Passo 5: Aggiungi il flusso dati inverso
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/n47gckhr/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/n47gckhr/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
Finora abbiamo costruito un'applicazione che visualizza correttamente come una funzione di proprietà e stato che fluiscono verso il basso della gerarchia. Adesso è il momento di supportare il flusso dei dati nella direzione opposta: i componenti del modulo in profondità nella gerarchia devono aggiornare lo stato in `FilterableProductTable`.

6
docs/thinking-in-react.ko-KR.md

@ -61,7 +61,7 @@ React의 많은 뛰어난 점들 중 하나는 생각을 하면서 애플리케
## 2단계: 정적 버전을 만드세요.
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/yun1vgqb/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/yun1vgqb/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
계층구조의 컴포넌트들을 가지고 있으니, 이젠 애플리케이션을 구현할 시간입니다. 가장 쉬운 방법은 상호작용을 하지 않는 채로 자료 모델을 이용해 UI를 그리는 것입니다. 정적 버전을 만드는 데에는 적은 생각과 많은 노동이 필요하고, 상호작용을 추가하는 데에는 많은 생각과 적은 노동이 필요하기 때문에 둘을 분리하는 것이 가장 좋습니다. 왜 그런지 봅시다.
@ -105,7 +105,7 @@ product 들의 원본 목록은 props를 통해서 전달되기 때문에, state
## 4단계: 어디서 state가 유지되어야 하는지 확인하세요.
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/zafjbw1e/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/zafjbw1e/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
이제 최소한의 state가 무엇인지 알아냈습니다. 다음은, 어떤 컴포넌트가 이 state를 변형하거나 만들어낼지 알아내야 합니다.
@ -130,7 +130,7 @@ product 들의 원본 목록은 props를 통해서 전달되기 때문에, state
## 5단계: 반대방향 자료 흐름을 추가하세요.
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/n47gckhr/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/n47gckhr/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
앞서 우리는 계층적으로 아랫방향 흐름의 props, state전달로 잘 동작하는 애플리케이션을 만들었습니다. 이제 다른방향의 자료 흐름을 지원할 시간입니다: form 컴포넌트들은 `FilterableProductTable`의 state를 업데이트할 필요성이 있죠.

6
docs/thinking-in-react.md

@ -61,7 +61,7 @@ Now that we've identified the components in our mock, let's arrange them into a
## Step 2: Build a static version in React
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/yun1vgqb/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/yun1vgqb/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
Now that you have your component hierarchy, it's time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why.
@ -105,7 +105,7 @@ So finally, our state is:
## Step 4: Identify where your state should live
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/zafjbw1e/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/zafjbw1e/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
OK, so we've identified what the minimal set of app state is. Next, we need to identify which component mutates, or *owns*, this state.
@ -130,7 +130,7 @@ You can start seeing how your application will behave: set `filterText` to `"bal
## Step 5: Add inverse data flow
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/n47gckhr/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/n47gckhr/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
So far, we've built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it's time to support data flowing the other way: the form components deep in the hierarchy need to update the state in `FilterableProductTable`.

116
docs/thinking-in-react.zh-CN.md

@ -8,13 +8,13 @@ redirect_from: 'blog/2013/11/05/thinking-in-react.html'
by Pete Hunt
在我看来,React 是构建大型,快速 web app 的首选方式。它已经在 Facebook 和 Instagram 被我们有了广泛的应用。
在我看来,React 是构建大型,快速 Web app 的首选方式。它已经在 Facebook 和 Instagram 被我们有了广泛的应用。
React许多优秀的部分之一是它如何使你随着构建 app 来思考 app。在本文里,我将带领你学习一个用 React 构建可搜索的数据表的思考过程。
React 许多优秀的部分之一,是它使得你在构建 app 的过程中不断思考。在本文里,我将带你经历一次使用 React 构建可搜索的商品数据表的思考过程。
## 从模型(mock)开始
想象我们已经有个一个 JSON API 和一个来自设计师的模型。我们的设计师似乎不是很好因为模型看起来像是这样:
想象我们已经有个一个 JSON API 和一个来自设计师的模型。我们的设计师显然做得不够好,因为模型看起来像这样:
![Mockup](/react/img/blog/thinking-in-react-mock.png)
@ -33,25 +33,25 @@ React许多优秀的部分之一是它如何使你随着构建 app 来思考 app
## 第一步:把UI拆分为一个组件的层级
首先你想要做的是在模型里的每一个组建周围绘制边框并给他们命名。如果你和设计师一起工作,他们应该已经完成这步了,所以去和他们谈谈!他们的photoshop图层名也许最终会成为你的React组件名。
首先你想要做的,是在模型里的每一个组件周围绘制边框,并给它们命名。如果你和设计师一起工作,他们应该已经完成这步了,所以去和他们谈谈!他们的 Photoshop 图层名也许最终会成为你的 React 组件名。
但是你如何知道什么东西应该是独立的组件?只需使用你决定是否创建一个函数或者对象的相同技术。这样一种技术是[single responsibility principle](https://en.wikipedia.org/wiki/Single_responsibility_principle),即是,一个组件在理想情况下只做一件事情。如果它最终变大,它就应该被分解为更小的组件。
但是你如何知道什么东西应该是独立的组件?只需在你创建一个函数或者对象时,根据是否使用过相同技术来做决定。一种这样的技术是[单一功能原则(single responsibility principle)](https://en.wikipedia.org/wiki/Single_responsibility_principle),也就是一个组件在理想情况下只做一件事情。如果它最终增长了,它就应该被分解为更小的组件。
既然你频繁显示一个JSON的数据模型给用户,你会发现,如果你的模型构建正确,你的UI(因此也有你的组件结构)就将映射良好.那是因为UI和数据模型趋向于附着于相同的 *信息架构*,这意味着把你的 UI 分离为组件的工作通常是简单的,只需把他拆成精确对应代表你的数据模型的每一块的组件.
既然你频繁显示一个 JSON 的数据模型给用户,你会发现,如果你的模型构建正确,你的 UI(因此也有你的组件结构)就将映射良好。那是因为 UI 和数据模型趋向附着于相同的 *信息架构*,这意味着,把你的 UI 分离为组件的工作通常是琐碎的,只需把 UI 拆分成能准确对应数据模型的每块组件。
![Component diagram](/react/img/blog/thinking-in-react-components.png)
在这里你会看到,在我们简单的APP里有五个组件.我用斜体表示每个组件的数据.
在这里你会看到,在我们的简单 APP 里有五个组件。我用斜体表示每个组件的数据。
1. **`FilterableProductTable` (orange):** 包含示例的整体
2. **`SearchBar` (blue):** 接受所有 *用户输入*
3. **`ProductTable` (green):** 基于 *用户输入* 显示和过滤 *数据集合(data collection)*
4. **`ProductCategoryRow` (turquoise):** 为每个 *分类* 显示一个列表头
5. **`ProductRow` (red):** 为每个 *产品* 显示一个
1. **`FilterableProductTable` (橙色):** 包含示例的整体
2. **`SearchBar` (蓝色):** 接收所有 *用户输入*
3. **`ProductTable` (绿色):** 基于 *用户输入* 显示和过滤 *数据集合(data collection)*
4. **`ProductCategoryRow` (蓝绿色):** 为每个 *分类* 显示一个列表头
5. **`ProductRow` (红色):** 为每个 *商品* 显示一
如果你看着 `ProductTable`,你会看到表的头(包含了 "Name" 和 "Price" 标签) 不是独立的组件.这是一个个人喜好问题,并且无论哪种方式都有争论.对于这个例子,我把它留做 `ProductTable` 的一部分,因为它是 *data collection*渲染的一部分,而 *data collection*渲染是 `ProductTable` 的职责.然而,当列表头增长到复杂的时候(例如 如果我们添加排序的功能性),那么无疑的使它成为独立的 `ProductTableHeader` 组件是有意义的.
如果你看着 `ProductTable`,你会看到表头(包含了 "Name" 和 "Price" 标签) 不是独立的组件。这是一个个人喜好问题,并且无论采用哪种方式都有争论。对于这个例子,我把它留做 `ProductTable` 的一部分,因为它是 *data collection*渲染的一部分,而 *data collection* 渲染是 `ProductTable` 的职责。然而,当列表头增长到复杂的时候(例如 如果我们添加排序功能),那么使它成为独立的 `ProductTableHeader` 组件无疑是有意义的。
既然现在我们已经识别出了我们模型中的组件,让我们把他们安排到一个层级中.这很容易. 在模型中出现在其他组件中的组件 同样应该在层级中表现为一个子级:
既然现在我们已经识别出了我们模型中的组件,让我们把他们安排到一个层级中。这很容易。在模型中,出现在一个组件里面的另一组件 ,应该在层级中表现为一种子级关系:
* `FilterableProductTable`
* `SearchBar`
@ -59,89 +59,89 @@ React许多优秀的部分之一是它如何使你随着构建 app 来思考 app
* `ProductCategoryRow`
* `ProductRow`
## Step 2: 用React创建一个静态版本
## 第二步:用React创建一个静态版本
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/yun1vgqb/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/yun1vgqb/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
既然你已经有了你的组件层级,时候实现你的app了.简单的方式是构建一个版本,它采取你的数据模型并渲染UI但是没有互动性.最好是分离这些过程,因为构建一个静态版本需要无脑的打很多字,然而添加互动性需要很多思考但不需要打太多字.我们会看到是为什么:
既然你已经有了你的组件层级,是时候实现你的app了。简单的方式是构建一个版本,它取走你的数据模型并渲染UI,除了没有互动性。这是将过程解耦的最好办法,因为构建一个静态版本需要不假思索地写很多代码,而添加互动性需要很多思考但不需要太多代码。之后我们将会看到原因。
要构建一个渲染你的数据模型的 app 的静态版本,你会想构建一个重用其他组件并利用 *props* 传递数据的组件. *props* 是一种从父级传递数据到子级的方式.如果你对 *state* 的观念很熟悉, **绝不要用state** 来构建这个静态版本.State 仅仅是为互动预留的,即,随时间变化的数据. 因为这是一个静态版本的app,你不需要它.
要构建一个静态版本 app 来渲染你的数据模型,你将会想到构建一个重用其它组件并利用 *props* 传递数据的组件。*props* 是一种从父级传递数据到子级的方式。如果你对 *state* 的观念很熟悉,**绝不要用state** 来构建这个静态版本。State 仅仅是为互动性,也就是随时间变化的数据所预留的。由于这是一个静态版本,你还不需要用到它。
你可以自顶向下或自底向上的构建.也就是说,你可以既从较高的层级(如 从 `FilterableProductTable` 开始) 也可以从较低的层级(`ProductRow`)开始构建组件. 在较简单的例子里,通常自顶向下要容易一些,然而在更大的项目上 自底向上更容易,并且伴随着构建写测试较容易.
你可以自顶向下或自底向上的构建。也就是说,你可以既从较高的层级(比如从 `FilterableProductTable` 开始)也可以从较低的层级(`ProductRow`)开始构建组件。在较简单的例子里,通常自顶向下要容易一些,然而在更大的项目上,自底向上地构建更容易,并且更方便伴随着构建写测试。
在这一步的最后,你会有一个渲染你数据模型的可重用的组件库. 这些组件将只含有 `render()` 方法因为这是一个你的app的静态版本. 在层级顶端的组件 (`FilterableProductTable`) 将会接受你的数据模型作为一个prop.如果你对你的底层数据模型做了变化并且再次调用 `ReactDOM.render()` ,UI将会更新.很容易看到你的UI是如何更新以及哪里来作出变动,因为这里没有任何复杂的事情发生. React的 **单向数据流** (也被称为 *单向绑定* )保持了每个东西模块化和快速.
在这一步的最后,你会获得一个渲染数据模型的可重用组件库。这些组件只有 `render()` 方法,因为这是一个静态版本。在层级顶端的组件 (`FilterableProductTable`) 将会接受你的数据模型,并将其作为一个prop。如果你改变了底层数据模型,并且再次调用 `React.render()` ,UI 将会更新。你可以很容易地看到 UI 是如何更新的,以及哪里变动了,因为这没什么复杂的。React的 **单向数据流** (也被称为 *单向绑定*)使一切保持了模块化和快速。
如果你执行这步需要帮助,请参考 [React docs](/react/docs/) .
如果你在执行这步时需要帮助,请参阅 [React 文档](/react/docs/)。
### 小插曲: props vs state
在React里有两种数据 "模型":props和state.明白这二者之间的区别是很重要的;如果你不是很确定不同是什么,请概览[React官方文档](/react/docs/interactivity-and-dynamic-uis-zh-CN.html)
在React里有两种数据 "模型": props 和 state。明白这二者之间的区别是很重要的;如果你不是很确定它们之间的区别,请概览[React官方文档](/react/docs/interactivity-and-dynamic-uis-zh-CN.html)
## 第三步:确定最小(但完备)的 UI state 的表达
## 第三步:确定最小(但完备)的 UI state 表达
要让你的UI互动,你需要能够触发变化到你的底层数据模型上.React用 **state** 来让此变得容易.
要让你的 UI 互动,你需要做到触发底层数据模型发生变化。React用 **state** 来让此变得容易。
要正确的构建你的app,你首先需要思考你的app需要的可变state的最小组. 这里的关键是 DRY: *Don't Repeat Yourself(不要重复自己)*.想出哪些是你的应用需要的绝对最小 state 表达,并按需计算其他任何数据.例如,如果你要构建一个 TODO list,只要保持一个 TODO 项的数组;不要为了计数保持一个单独的 state 变量.作为替代,当你想渲染 TODO 数量时,简单的采用TODO项目数组的长度.
要正确的构建你的 app,你首先需要思考你的 app 需要的可变 state 的最小组。这里的关键是 DRY 原则:*Don't Repeat Yourself(不要重复自己)*。想出哪些是你的应用需要的绝对最小 state 表达,并按需计算其他任何数据。例如,如果你要构建一个 TODO list,只要保持一个 TODO 项的数组;不要为了计数保持一个单独的 state 变量。当你想渲染 TODO 的计数时,简单的采用 TODO 项目的数组长度作为替代。
考虑我们例子应用中数据的所有块.我们有:
考虑我们示例应用中的数据所有块,包括:
* 原始的品列表
* 原始的品列表
* 用户输入的搜索文本
* checkbox的值
* 产品的滤过的列表
* 复选框的值
* 商品的过滤列表
让我们遍历每一个并指出哪一个是state.简单的问三个关于每个数据块的问题:
让我们逐个检查出哪一个是state,只需要简单地问以下三个问题:
1. 它是通过props从父级传递来的吗?如果是,它可能不是state.
2. 它随时间变化吗?如果不是,它可能不是state.
3. 你能基于其他任何组件里的 state 或者 props 计算出它吗?如果是,它可能不是state.
1. 它是通过props从父级传递来的吗?如果是,它可能不是 state。
2. 它随时间变化吗?如果不是,它可能不是 state。
3. 你能基于其他任何组件里的 state 或者 props 计算出它吗如果是,它可能不是state.
原始的产品列表被以 props 传入,所以它不是 state. 搜索文本和 checkbox 看起来是state 因为他们随时间变化并且不能从任何东西计算出.最后,产品滤过的列表不是state因为它可以联合原始列表与搜索文本及 checkbox 的值计算出.
原始的商品列表以 props 传入,所以它不是 state。搜索文本和复选框看起来是 state,因为他们随时间变化并且不能从任何东西计算出。最后,过滤出的商品列表不是 state,因为它可以通过原始列表与搜索文本及复选框的值组合计算得出。
所以最后,我们的 state 是:
* 用户输入的搜索文本
* checkbox 的值
## 第四步:确定你的 state 应该存在于哪里
## 第四步确定你的 state 应该存在于哪里
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/zafjbw1e/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/zafjbw1e/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
好,我们已经确定了app state 的最小组是什么.接下来,我们需要确定哪个组件变动,或者 *拥有*,这 个state.
OK,我们已经确定好应用的最小 state 集合是什么。接下来,我们需要确定哪个组件可以改变,或者 *拥有*个state.
记住:React都是关于单向数据流下组件层级的.可能不能立刻明白哪些组件应该拥有哪些 state. **这常常对于新手在理解上是最具挑战的一部分,** 所以跟着这几步来弄明白它:
记住:React 总是在组件层级中单向数据流动的。可能不能立刻明白哪些组件应该拥有哪些 state。 **这对于新手在理解上经常是最具挑战的一部分,** 所以跟着这几步来弄明白它:
对于你的应用里每一个数据块:
对于你的应用里每一个数据块
* 基于 state 确定每个绘制某些东西的组件
* 找到一个共同拥有者的组件(在层级中所有组件之上需要这个state的单个组件)
* 要么是共同拥有者,要么是其他在层级里更高级的组件应该拥有这个state
* 如果你不能找到一个组件,它拥有这个state有意义,创建一个新的组件简单的为了持有此state,并把它在层级里添加比共同拥有者组件更高的层级上.
* 确定哪些组件要基于 state 来渲染内容。
* 找到一个共同的拥有者组件(在所有需要这个state组件的层次之上,找出共有的单一组件)。
* 要么是共同拥有者要么是其他在层级里更高级的组件应该拥有这个state
* 如果你不能找到一个组件让其可以有意义地拥有这个 state,可以简单地创建一个新的组件 hold 住这个state,并把它添加到比共同拥有者组件更高的层级上。
让我们过一遍这个用于我们应用的策略:
让我们使用这个策略浏览一遍我们的应用:
* `ProductTable` 需要基于 state 过滤产品列表,`SearchBar` 需要显示搜索文本和选择状态.
* 共同拥有者组件是`FilterableProductTable` .
* 对于过滤文本和选择值存在于 `FilterableProductTable` 观念上是有意义的.
* `ProductTable` 需要基于 state 过滤产品列表,`SearchBar` 需要显示搜索文本和选择状态。
* 共同拥有者组件是 `FilterableProductTable`
* 对于过滤文本和选择框值存在于 `FilterableProductTable`,从概念上讲是有意义的。
,我们已经决定了我们的state存在于 `FilterableProductTable` .首先,添加一个 `getInitialState()` 方法到 `FilterableProductTable` ,返回 `{filterText: '', inStockOnly: false}` 来反映你的应用的初始状态. 然后,传递`filterText` 和 `inStockOnly``ProductTable``SearchBar` 作为prop.最后,使用这些prop来过滤 `ProductTable` 中的行和设置`SearchBar`的表单项的值.
,我们已经决定了我们的 state 存在于 `FilterableProductTable`。首先,添加一个 `getInitialState()` 方法到 `FilterableProductTable`,返回 `{filterText: '', inStockOnly: false}` 来反映应用的初始状态。然后,传递`filterText` 和 `inStockOnly``ProductTable` `SearchBar` 作为 prop。最后,使用这些 prop 来过滤 `ProductTable` 中的行和设置 `SearchBar` 的表单项的值。
你可以开始看看你的应用将有怎样的行为: 设置 `filterText``"ball"` 并刷新你的app.你将看到数据表被正确更新了.
你可以开始看看你的应用将有怎样的行为: 设置 `filterText``"ball"` 并刷新你的 app。你将可以看到数据表被正确地更新。
## 第五步:添加反向数据流
## 第五步添加反向数据流
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/n47gckhr/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<iframe width="100%" height="600" src="https://jsfiddle.net/reactjs/n47gckhr/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
到目前为止,我们已经构建了一个应用, 它以props 和 state 沿着层级向下流动的功能正确渲染。现在是时候支持数据的另一种流动了:在层级深处的表单组件需要更新 `FilterableProductTable` 里的state.
到目前为止,我们已经构建了一个应用, 它以 props 和 state 沿着层级向下流动的功能正确渲染。现在是时候支持另一种数据流动了:在层级深处的表单组件需要更新 `FilterableProductTable` 里的 state。
React 让数据显式流动,使理解你的应用如何工作变得简单,但是相对于传统的双向数据绑定,确实需要多一些字。 React 提供了一个叫做 `ReactLink` 的插件来使这种模式和双向数据绑定一样方便,但是考虑到这篇文章的目的,我们将会保持所有东西都直截了当。
React 让数据显式流动,使理解应用如何工作变得简单,但是相对于传统的双向数据绑定,确实需要多一些字。React 提供了一个叫做 `ReactLink` 的插件来使这种模式和双向数据绑定一样方便,但是考虑到这篇文章的目的,我们将会保持所有东西都直截了当。
如果你尝试在当前版本的示例中输入或者选中复选框,你会发现 React 忽略了你的输入。这是有意的,因为已经设置了 `input``value` prop 总是与 `FilterableProductTable` 传递过来的 `state` 一致。
如果你尝试在当前版本的示例中输入或者选中复选框,你会发现 React 忽略了你的输入。这是有意的,因为我们已经设置了 `input``value` prop 总是与 `FilterableProductTable` 传递过来的 `state` 一致。
让我们思考下我们希望发生什么。我们想确保每当用户改变表单,我们就更新 state 来反映用户的输入。由于组件应该只更新自己拥有的 state , `FilterableProductTable` 将会传递一个回调函数给 `SearchBar`此函数每当 state 应被改变时就会击发。我们可以使用 input 的 `onChange` 事件来接受它的通知。 `FilterableProductTable` 传递的回调函数将会调用 `setState()` ,然后应用将会被更新。
让我们思考下希望发生什么。我们想确保每当用户改变表单,就通过更新 state 来反映用户的输入。由于组件应该只更新自己拥有的 state , `FilterableProductTable` 将会传递一个回调函数给 `SearchBar`每当 state 应被更新时回调函数就会被调用。我们可以使用 input 的 `onChange` 事件来接受它的通知。 `FilterableProductTable` 传递的回调函数将会调用 `setState()` ,然后应用将会被更新。
虽然这听起来复杂,但是实际上只是数行代码。并且数据在应用中从始至终如何流动是非常明确的。
虽然这听起来复杂,但是实际上只是数行代码。并且这明确显示出了数据在应用中从始至终如何流动的。
## 好了,就是这样
## 好了就是这样
希望,这给了你一个怎样思考用React构建组件和应用的概念。虽然可能比你通常要输入更多的代码,记住,读代码的时间远比写代码的时间多,并且阅读这种模块化的,显式的代码是极端容易的。当你开始构建大型组件库时,你会非常感激这种清晰性和模块化,并且随着代码的重用,你的代码行数将会开始缩减. :)。
希望这给了你一个怎样思考用React构建组件和应用的概念。虽然可能比你过往的习惯要多敲一点代码,但记住,读代码的时间远比写代码的时间多,并且阅读这种模块化的、显式的代码是极为容易的。当你开始构建大型组件库时,你会非常感激这种清晰性和模块化,并且随着代码的重用,你的代码行数将会开始缩减。:)

BIN
downloads/react-0.14.4.zip

Binary file not shown.

BIN
downloads/react-0.14.5.zip

Binary file not shown.

BIN
downloads/react-0.14.6.zip

Binary file not shown.

BIN
img/docs/should-component-update.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 44 KiB

2
js/react-dom.js

@ -1,5 +1,5 @@
/**
* ReactDOM v0.14.3
* ReactDOM v0.14.6
*
* Copyright 2013-2015, Facebook, Inc.
* All rights reserved.

44
js/react.js

@ -1,5 +1,5 @@
/**
* React v0.14.3
* React v0.14.6
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.React = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
/**
@ -3343,8 +3343,8 @@ var HTMLDOMPropertyConfig = {
*/
// autoCapitalize and autoCorrect are supported in Mobile Safari for
// keyboard hints.
autoCapitalize: null,
autoCorrect: null,
autoCapitalize: MUST_USE_ATTRIBUTE,
autoCorrect: MUST_USE_ATTRIBUTE,
// autoSave allows WebKit/Blink to persist values of input fields on page reloads
autoSave: null,
// color is for Safari mask-icon link
@ -3375,9 +3375,7 @@ var HTMLDOMPropertyConfig = {
httpEquiv: 'http-equiv'
},
DOMPropertyNames: {
autoCapitalize: 'autocapitalize',
autoComplete: 'autocomplete',
autoCorrect: 'autocorrect',
autoFocus: 'autofocus',
autoPlay: 'autoplay',
autoSave: 'autosave',
@ -7750,7 +7748,7 @@ function updateOptionsIfPendingUpdateAndMounted() {
var value = LinkedValueUtils.getValue(props);
if (value != null) {
updateOptions(this, props, value);
updateOptions(this, Boolean(props.multiple), value);
}
}
}
@ -8822,7 +8820,9 @@ var DOM_OPERATION_TYPES = {
'setValueForProperty': 'update attribute',
'setValueForAttribute': 'update attribute',
'deleteValueForProperty': 'remove attribute',
'dangerouslyReplaceNodeWithMarkupByID': 'replace'
'setValueForStyles': 'update styles',
'replaceNodeWithMarkup': 'replace',
'updateTextContent': 'set textContent'
};
function getTotalTime(measurements) {
@ -13840,7 +13840,7 @@ module.exports = ReactUpdates;
'use strict';
module.exports = '0.14.3';
module.exports = '0.14.6';
},{}],85:[function(_dereq_,module,exports){
/**
* Copyright 2013-2015, Facebook, Inc.
@ -18070,11 +18070,14 @@ module.exports = focusNode;
* @typechecks
*/
/* eslint-disable fb-www/typeof-undefined */
/**
* Same as document.activeElement but wraps in a try-catch block. In IE it is
* not safe to call document.activeElement if there is nothing focused.
*
* The activeElement will be null only if the document or document body is not yet defined.
* The activeElement will be null only if the document or document body is not
* yet defined.
*/
'use strict';
@ -18082,7 +18085,6 @@ function getActiveElement() /*?DOMElement*/{
if (typeof document === 'undefined') {
return null;
}
try {
return document.activeElement || document.body;
} catch (e) {
@ -18325,7 +18327,7 @@ module.exports = hyphenateStyleName;
* will remain to ensure logic does not differ in production.
*/
var invariant = function (condition, format, a, b, c, d, e, f) {
function invariant(condition, format, a, b, c, d, e, f) {
if ("development" !== 'production') {
if (format === undefined) {
throw new Error('invariant requires an error message argument');
@ -18339,15 +18341,16 @@ var invariant = function (condition, format, a, b, c, d, e, f) {
} else {
var args = [a, b, c, d, e, f];
var argIndex = 0;
error = new Error('Invariant Violation: ' + format.replace(/%s/g, function () {
error = new Error(format.replace(/%s/g, function () {
return args[argIndex++];
}));
error.name = 'Invariant Violation';
}
error.framesToPop = 1; // we don't care about invariant's own frame
throw error;
}
};
}
module.exports = invariant;
},{}],145:[function(_dereq_,module,exports){
@ -18609,19 +18612,24 @@ module.exports = performance || {};
'use strict';
var performance = _dereq_(151);
var curPerformance = performance;
var performanceNow;
/**
* Detect if we can use `window.performance.now()` and gracefully fallback to
* `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now
* because of Facebook's testing infrastructure.
*/
if (!curPerformance || !curPerformance.now) {
curPerformance = Date;
if (performance.now) {
performanceNow = function () {
return performance.now();
};
} else {
performanceNow = function () {
return Date.now();
};
}
var performanceNow = curPerformance.now.bind(curPerformance);
module.exports = performanceNow;
},{"151":151}],153:[function(_dereq_,module,exports){
/**

6
tips/10-props-in-getInitialState-as-anti-pattern.md

@ -11,7 +11,9 @@ next: dom-event-listeners.html
>
> This isn't really a React-specific tip, as such anti-patterns often occur in code in general; in this case, React simply points them out more clearly.
Using props, passed down from parent, to generate state in `getInitialState` often leads to duplication of "source of truth", i.e. where the real data is. Whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble.
Using props to generate state in `getInitialState` often leads to duplication of "source of truth", i.e. where the real data is. This is because `getInitialState` is only invoked when the component is first created.
Whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble.
**Bad example:**
@ -43,7 +45,7 @@ ReactDOM.render(<MessageBox name="Rogers"/>, mountNode);
(For more complex logic, simply isolate the computation in a method.)
However, it's **not** an anti-pattern if you make it clear that synchronization's not the goal here:
However, it's **not** an anti-pattern if you make it clear that the prop is only seed data for the component's internally-controlled state:
```js
var Counter = React.createClass({

2
tips/18-use-react-with-other-libraries.ko-KR.md

@ -16,7 +16,7 @@ var App = React.createClass({
},
componentDidMount: function() {
$(ReactDOM.findDOMNode(this.refs.placeholder)).append($('<span />'));
$(this.refs.placeholder).append($('<span />'));
},
componentWillUnmount: function() {

2
tips/18-use-react-with-other-libraries.md

@ -16,7 +16,7 @@ var App = React.createClass({
},
componentDidMount: function() {
$(ReactDOM.findDOMNode(this.refs.placeholder)).append($('<span />'));
$(this.refs.placeholder).append($('<span />'));
},
componentWillUnmount: function() {

Loading…
Cancel
Save