Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a2312c8e5 | ||
|
|
01622a4442 | ||
|
|
a4fd08973b | ||
|
|
c2dd57c6a6 | ||
|
|
db23e49467 | ||
|
|
3117584e0e | ||
|
|
26258313cd | ||
|
|
d602f1d3fb | ||
|
|
c181b824ca | ||
|
|
d6100a703f | ||
|
|
afef42e377 | ||
|
|
24059873ac | ||
|
|
bac2462dd5 | ||
|
|
878482154e | ||
|
|
bfba064631 | ||
|
|
0f6a151650 | ||
|
|
f0782e2b2e | ||
|
|
b247f68b33 | ||
|
|
6e2450e8f2 | ||
|
|
c2dde8df0b | ||
|
|
aaf8f870cb | ||
|
|
4952cd00d4 | ||
|
|
eadbf33296 | ||
|
|
12cafa7e00 | ||
|
|
090c2dd833 | ||
|
|
c469697ad7 | ||
|
|
d8a9cd365c | ||
|
|
6323f03148 | ||
|
|
6384e56d8d | ||
|
|
84f6915315 | ||
|
|
fdb2486b98 | ||
|
|
fb620be2b8 | ||
|
|
0acdefb7cc | ||
|
|
e0f74c6c6c | ||
|
|
8ab0651158 | ||
|
|
712c6cb1d8 | ||
|
|
e931e02a36 | ||
|
|
6c84e3d410 | ||
|
|
e8b5c75c0f | ||
|
|
b5524faa4b | ||
|
|
411726dcf1 | ||
|
|
28f242d0b4 | ||
|
|
5cc9abfe60 | ||
|
|
348a37cc99 | ||
|
|
bed6aefc46 | ||
|
|
1e175d0858 | ||
|
|
193e4cf582 | ||
|
|
b0aa296519 | ||
|
|
b020e69edc | ||
|
|
d69657bca4 | ||
|
|
8812c6b678 | ||
|
|
60e30f1da4 | ||
|
|
e4300d951c | ||
|
|
13f3cdeeb1 | ||
|
|
fe085c1cce | ||
|
|
b71499e5f4 | ||
|
|
df0dac72c2 | ||
|
|
5f2a80c086 | ||
|
|
e21f1c7759 | ||
|
|
21588d900f | ||
|
|
5039dad053 | ||
|
|
b120cdafb2 | ||
|
|
f93bb3aa6a | ||
|
|
ac2853b5d4 | ||
|
|
007cf55872 | ||
|
|
ec7947979b | ||
|
|
24f7659b7c | ||
|
|
c2443c227c | ||
|
|
3603d45157 | ||
|
|
0811e63e22 | ||
|
|
3917c04f16 |
103
CHANGELOG.md
103
CHANGELOG.md
@@ -1,3 +1,106 @@
|
||||
## 0.14.2 (November 2, 2015)
|
||||
|
||||
### React DOM
|
||||
- Fixed bug with development build preventing events from firing in some versions of Internet Explorer & Edge
|
||||
- Fixed bug with development build when using es5-sham in older versions of Internet Explorer
|
||||
- Added support for `integrity` attribute
|
||||
- Fixed bug resulting in `children` prop being coerced to a string for custom elements, which was not the desired behavior
|
||||
- Moved `react` from `dependencies` to `peerDependencies` to match expectations and align with `react-addons-*` packages
|
||||
|
||||
|
||||
## 0.14.1 (October 28, 2015)
|
||||
|
||||
### React DOM
|
||||
- Fixed bug where events wouldn't fire in old browsers when using React in development mode
|
||||
- Fixed bug preventing use of `dangerouslySetInnerHTML` with Closure Compiler Advanced mode
|
||||
- Added support for `srcLang`, `default`, and `kind` attributes for `<track>` elements
|
||||
- Added support for `color` attribute
|
||||
- Ensured legacy `.props` access on DOM nodes is updated on re-renders
|
||||
|
||||
### React TestUtils Add-on
|
||||
- Fixed `scryRenderedDOMComponentsWithClass` so it works with SVG
|
||||
|
||||
### React CSSTransitionGroup Add-on
|
||||
- Fix bug preventing `0` to be used as a timeout value
|
||||
|
||||
### React on Bower
|
||||
- Added `react-dom.js` to `main` to improve compatibility with tooling
|
||||
|
||||
|
||||
## 0.14.0 (October 7, 2015)
|
||||
|
||||
### Major changes
|
||||
|
||||
- Split the main `react` package into two: `react` and `react-dom`. This paves the way to writing components that can be shared between the web version of React and React Native. This means you will need to include both files and some functions have been moved from `React` to `ReactDOM`.
|
||||
- Addons have been moved to seperate packages (`react-addons-clone-with-props`, `react-addons-create-fragment`, `react-addons-css-transition-group`, `react-addons-linked-state-mixin`, `react-addons-perf`, `react-addons-pure-render-mixin`, `react-addons-shallow-compare`, `react-addons-test-utils`, `react-addons-transition-group`, `react-addons-update`, `ReactDOM.unstable_batchedUpdates`).
|
||||
- Stateless functional components - React components were previously created using React.createClass or using ES6 classes. This release adds a [new syntax](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions) where a user defines a single [stateless render function](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions) (with one parameter: `props`) which returns a JSX element, and this function may be used as a component.
|
||||
- Refs to DOM components as the DOM node itself. Previously the only useful thing you can do with a DOM component is call `getDOMNode()` to get the underlying DOM node. Starting with this release, a ref to a DOM component _is_ the actual DOM node. **Note that refs to custom (user-defined) components work exactly as before; only the built-in DOM components are affected by this change.**
|
||||
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- `React.initializeTouchEvents` is no longer necessary and has been removed completely. Touch events now work automatically.
|
||||
- Add-Ons: Due to the DOM node refs change mentioned above, `TestUtils.findAllInRenderedTree` and related helpers are no longer able to take a DOM component, only a custom component.
|
||||
- The `props` object is now frozen, so mutating props after creating a component element is no longer supported. In most cases, [`React.cloneElement`](/react/docs/top-level-api.html#react.cloneelement) should be used instead. This change makes your components easier to reason about and enables the compiler optimizations mentioned above.
|
||||
- Plain objects are no longer supported as React children; arrays should be used instead. You can use the [`createFragment`](/react/docs/create-fragment.html) helper to migrate, which now returns an array.
|
||||
- Add-Ons: `classSet` has been removed. Use [classnames](https://github.com/JedWatson/classnames) instead.
|
||||
- Web components (custom elements) now use native property names. Eg: `class` instead of `className`.
|
||||
|
||||
### Deprecations
|
||||
|
||||
- `this.getDOMNode()` is now deprecated and `ReactDOM.findDOMNode(this)` can be used instead. Note that in the common case, `findDOMNode` is now unnecessary since a ref to the DOM component is now the actual DOM node.
|
||||
- `setProps` and `replaceProps` are now deprecated. Instead, call ReactDOM.render again at the top level with the new props.
|
||||
- ES6 component classes must now extend `React.Component` in order to enable stateless function components. The [ES3 module pattern](/react/blog/2015/01/27/react-v0.13.0-beta-1.html#other-languages) will continue to work.
|
||||
- Reusing and mutating a `style` object between renders has been deprecated. This mirrors our change to freeze the `props` object.
|
||||
- Add-Ons: `cloneWithProps` is now deprecated. Use [`React.cloneElement`](/react/docs/top-level-api.html#react.cloneelement) instead (unlike `cloneWithProps`, `cloneElement` does not merge `className` or `style` automatically; you can merge them manually if needed).
|
||||
- Add-Ons: To improve reliability, `CSSTransitionGroup` will no longer listen to transition events. Instead, you should specify transition durations manually using props such as `transitionEnterTimeout={500}`.
|
||||
|
||||
### Notable enhancements
|
||||
|
||||
- Added `React.Children.toArray` which takes a nested children object and returns a flat array with keys assigned to each child. This helper makes it easier to manipulate collections of children in your `render` methods, especially if you want to reorder or slice `this.props.children` before passing it down. In addition, `React.Children.map` now returns plain arrays too.
|
||||
- React uses `console.error` instead of `console.warn` for warnings so that browsers show a full stack trace in the console. (Our warnings appear when you use patterns that will break in future releases and for code that is likely to behave unexpectedly, so we do consider our warnings to be “must-fix” errors.)
|
||||
- Previously, including untrusted objects as React children [could result in an XSS security vulnerability](http://danlec.com/blog/xss-via-a-spoofed-react-element). This problem should be avoided by properly validating input at the application layer and by never passing untrusted objects around your application code. As an additional layer of protection, [React now tags elements](https://github.com/facebook/react/pull/4832) with a specific [ES2015 (ES6) `Symbol`](http://www.2ality.com/2014/12/es6-symbols.html) in browsers that support it, in order to ensure that React never considers untrusted JSON to be a valid element. If this extra security protection is important to you, you should add a `Symbol` polyfill for older browsers, such as the one included by [Babel’s polyfill](http://babeljs.io/docs/usage/polyfill/).
|
||||
- When possible, React DOM now generates XHTML-compatible markup.
|
||||
- React DOM now supports these standard HTML attributes: `capture`, `challenge`, `inputMode`, `is`, `keyParams`, `keyType`, `minLength`, `summary`, `wrap`. It also now supports these non-standard attributes: `autoSave`, `results`, `security`.
|
||||
- React DOM now supports these SVG attributes, which render into namespaced attributes: `xlinkActuate`, `xlinkArcrole`, `xlinkHref`, `xlinkRole`, `xlinkShow`, `xlinkTitle`, `xlinkType`, `xmlBase`, `xmlLang`, `xmlSpace`.
|
||||
- The `image` SVG tag is now supported by React DOM.
|
||||
- In React DOM, arbitrary attributes are supported on custom elements (those with a hyphen in the tag name or an `is="..."` attribute).
|
||||
- React DOM now supports these media events on `audio` and `video` tags: `onAbort`, `onCanPlay`, `onCanPlayThrough`, `onDurationChange`, `onEmptied`, `onEncrypted`, `onEnded`, `onError`, `onLoadedData`, `onLoadedMetadata`, `onLoadStart`, `onPause`, `onPlay`, `onPlaying`, `onProgress`, `onRateChange`, `onSeeked`, `onSeeking`, `onStalled`, `onSuspend`, `onTimeUpdate`, `onVolumeChange`, `onWaiting`.
|
||||
- Many small performance improvements have been made.
|
||||
- Many warnings show more context than before.
|
||||
- Add-Ons: A [`shallowCompare`](https://github.com/facebook/react/pull/3355) add-on has been added as a migration path for `PureRenderMixin` in ES6 classes.
|
||||
- Add-Ons: `CSSTransitionGroup` can now use [custom class names](https://github.com/facebook/react/blob/48942b85/docs/docs/10.1-animation.md#custom-classes) instead of appending `-enter-active` or similar to the transition name.
|
||||
|
||||
### New helpful warnings
|
||||
|
||||
- React DOM now warns you when nesting HTML elements invalidly, which helps you avoid surprising errors during updates.
|
||||
- Passing `document.body` directly as the container to `ReactDOM.render` now gives a warning as doing so can cause problems with browser extensions that modify the DOM.
|
||||
- Using multiple instances of React together is not supported, so we now warn when we detect this case to help you avoid running into the resulting problems.
|
||||
|
||||
### Notable bug fixes
|
||||
|
||||
- Click events are handled by React DOM more reliably in mobile browsers, particularly in Mobile Safari.
|
||||
- SVG elements are created with the correct namespace in more cases.
|
||||
- React DOM now renders `<option>` elements with multiple text children properly and renders `<select>` elements on the server with the correct option selected.
|
||||
- When two separate copies of React add nodes to the same document (including when a browser extension uses React), React DOM tries harder not to throw exceptions during event handling.
|
||||
- Using non-lowercase HTML tag names in React DOM (e.g., `React.createElement('DIV')`) no longer causes problems, though we continue to recommend lowercase for consistency with the JSX tag name convention (lowercase names refer to built-in components, capitalized names refer to custom components).
|
||||
- React DOM understands that these CSS properties are unitless and does not append “px” to their values: `animationIterationCount`, `boxOrdinalGroup`, `flexOrder`, `tabSize`, `stopOpacity`.
|
||||
- Add-Ons: When using the test utils, `Simulate.mouseEnter` and `Simulate.mouseLeave` now work.
|
||||
- Add-Ons: ReactTransitionGroup now correctly handles multiple nodes being removed simultaneously.
|
||||
|
||||
|
||||
### React Tools / Babel
|
||||
|
||||
#### Breaking Changes
|
||||
|
||||
- The `react-tools` package and `JSXTransformer.js` browser file [have been deprecated](/react/blog/2015/06/12/deprecating-jstransform-and-react-tools.html). You can continue using version `0.13.3` of both, but we no longer support them and recommend migrating to [Babel](http://babeljs.io/), which has built-in support for React and JSX.
|
||||
|
||||
#### New Features
|
||||
|
||||
- Babel 5.8.24 introduces **Inlining React elements:** The `optimisation.react.inlineElements` transform converts JSX elements to object literals like `{type: 'div', props: ...}` instead of calls to `React.createElement`. This should only be enabled in production, since it disables some development warnings/checks.
|
||||
- Babel 5.8.24 introduces **Constant hoisting for React elements:** The `optimisation.react.constantElements` transform hoists element creation to the top level for subtrees that are fully static, which reduces calls to `React.createElement` and the resulting allocations. More importantly, it tells React that the subtree hasn’t changed so React can completely skip it when reconciling. This should only be enabled in production, since it disables some development warnings/checks.
|
||||
|
||||
|
||||
## 0.13.3 (May 8, 2015)
|
||||
|
||||
### React Core
|
||||
|
||||
12
README.md
12
README.md
@@ -1,4 +1,4 @@
|
||||
# [React](https://facebook.github.io/react/) [](https://travis-ci.org/facebook/react) [](http://badge.fury.io/js/react)
|
||||
# [React](https://facebook.github.io/react/) [](https://travis-ci.org/facebook/react) [](http://badge.fury.io/js/react)
|
||||
|
||||
React is a JavaScript library for building user interfaces.
|
||||
|
||||
@@ -21,7 +21,7 @@ var HelloMessage = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<HelloMessage name="John" />,
|
||||
document.getElementById('container')
|
||||
);
|
||||
@@ -37,12 +37,12 @@ The fastest way to get started is to serve JavaScript from the CDN (also availab
|
||||
|
||||
```html
|
||||
<!-- The core React library -->
|
||||
<script src="https://fb.me/react-0.13.3.js"></script>
|
||||
<!-- In-browser JSX transformer, remove when pre-compiling JSX. -->
|
||||
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
|
||||
<script src="https://fb.me/react-0.14.2.js"></script>
|
||||
<!-- The ReactDOM Library -->
|
||||
<script src="https://fb.me/react-dom-0.14.2.js"></script>
|
||||
```
|
||||
|
||||
We've also built a [starter kit](https://facebook.github.io/react/downloads/react-0.13.3.zip) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
|
||||
We've also built a [starter kit](https://facebook.github.io/react/downloads/react-0.14.2.zip) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
|
||||
|
||||
If you'd like to use [bower](http://bower.io), it's as easy as:
|
||||
|
||||
|
||||
@@ -36,4 +36,4 @@ sass:
|
||||
sass_dir: _css
|
||||
gems:
|
||||
- jekyll-redirect-from
|
||||
react_version: 0.14.0-alpha
|
||||
react_version: 0.14.1
|
||||
|
||||
@@ -1,44 +1,75 @@
|
||||
---
|
||||
- - Aaron Franks
|
||||
- - '839'
|
||||
- Aaron Franks
|
||||
- Aaron Gelter
|
||||
- Adam Krebs
|
||||
- Adam Mark
|
||||
- Adam Solove
|
||||
- Adam Timberlake
|
||||
- Adam Zapletal
|
||||
- Ahmad Wali Sidiqi
|
||||
- Alan Souza
|
||||
- Alan deLevie
|
||||
- Alastair Hole
|
||||
- Alex
|
||||
- Alex Boyd
|
||||
- Alex Lopatin
|
||||
- Alex Mykyta
|
||||
- Alex Pien
|
||||
- Alex Smith
|
||||
- Alex Zelenskiy
|
||||
- Alexander Shtuchkin
|
||||
- Alexander Solovyov
|
||||
- Alexander Tseung
|
||||
- Alexandre Gaudencio
|
||||
- Alexey Raspopov
|
||||
- Alexey Shamrin
|
||||
- Andre Z Sanchez
|
||||
- Andreas Savvides
|
||||
- Andreas Svensson
|
||||
- Andres Kalle
|
||||
- Andres Suarez
|
||||
- Andrew Cobby
|
||||
- Andrew Davey
|
||||
- Andrew Rasmussen
|
||||
- Andrew Sokolov
|
||||
- Andrew Zich
|
||||
- Andrey Popp
|
||||
- Anthony van der Hoorn
|
||||
- Antonio Ruberto
|
||||
- Antti Ahti
|
||||
- Anuj Tomar
|
||||
- AoDev
|
||||
- Areeb Malik
|
||||
- Aria Buckles
|
||||
- Aria Stewart
|
||||
- Arian Faurtosh
|
||||
- Artem Nezvigin
|
||||
- Austin Wright
|
||||
- Ayman Osman
|
||||
- Baraa Hamodi
|
||||
- Bartosz Kaszubowski
|
||||
- Basarat Ali Syed
|
||||
- Battaile Fauber
|
||||
- Beau Smith
|
||||
- Ben Alpert
|
||||
- Ben Anderson
|
||||
- Ben Foxall
|
||||
- Ben Jaffe
|
||||
- Ben Moss
|
||||
- Ben Newman
|
||||
- Ben Ripkens
|
||||
- Benjamin Keen
|
||||
- Benjamin Leiken
|
||||
- Benjamin Woodruff
|
||||
- Bill Fisher
|
||||
- Blaine Hatab
|
||||
- Blaine Kasten
|
||||
- Bob Eagan
|
||||
- Bob Ralian
|
||||
- Bob Renwick
|
||||
- Bojan Mihelac
|
||||
- Bradley Spaulding
|
||||
- Brandon Bloom
|
||||
- Brandon Tilley
|
||||
- Brian Cooke
|
||||
@@ -51,103 +82,166 @@
|
||||
- Bruno Škvorc
|
||||
- Cam Song
|
||||
- Cam Spiers
|
||||
- Carter Chung
|
||||
- Cassus Adam Banko
|
||||
- Cat Chen
|
||||
- Cedric Sohrauer
|
||||
- Charles Marsh
|
||||
- Chase Adams
|
||||
- Cheng Lou
|
||||
- Chitharanjan Das
|
||||
- Chris Grovers
|
||||
- Chris Ha
|
||||
- Chris Rebert
|
||||
- Chris Sciolla
|
||||
- Christian
|
||||
- Christian Alfoni
|
||||
- Christian Oliff
|
||||
- Christian Roman
|
||||
- Christoph Pojer
|
||||
- Christopher Monsanto
|
||||
- Clay Allsopp
|
||||
- Connor McSheffrey
|
||||
- Cory House
|
||||
- Cotton Hou
|
||||
- Cristovao Verstraeten
|
||||
- Damien Pellier
|
||||
- Dan Abramov
|
||||
- Dan Fox
|
||||
- Dan Schafer
|
||||
- Daniel Carlsson
|
||||
- Daniel Cousens
|
||||
- Daniel Friesen
|
||||
- Daniel Gasienica
|
||||
- Daniel Hejl
|
||||
- Daniel Lo Nigro
|
||||
- Daniel Mané
|
||||
- Daniel Miladinov
|
||||
- Daniel Rodgers-Pryor
|
||||
- Daniel Schonfeld
|
||||
- Danny Ben-David
|
||||
- Darcy
|
||||
- Daryl Lau
|
||||
- Darío Javier Cravero
|
||||
- David Baker
|
||||
- David Goldberg
|
||||
- David Greenspan
|
||||
- David Hellsing
|
||||
- David Hu
|
||||
- David Mininger
|
||||
- David Neubauer
|
||||
- David Percy
|
||||
- Denis Sokolov
|
||||
- Dennis Johnson
|
||||
- Devon Blandin
|
||||
- Devon Harvey
|
||||
- Dmitrii Abramov
|
||||
- Dmitry Blues
|
||||
- Dmitry Mazuro
|
||||
- Domenico Matteo
|
||||
- Don Abrams
|
||||
- Dustan Kasten
|
||||
- Dustin Getz
|
||||
- Dylan Harrington
|
||||
- Eduardo Garcia
|
||||
- Edvin Erikson
|
||||
- Elaine Fang
|
||||
- Enguerran
|
||||
- Eric Clemmons
|
||||
- Eric Eastwood
|
||||
- Eric Florenzano
|
||||
- Eric O'Connell
|
||||
- Eric Schoffstall
|
||||
- Erik Harper
|
||||
- Espen Hovlandsdal
|
||||
- Evan Coonrod
|
||||
- Fabio M. Costa
|
||||
- Federico Rampazzo
|
||||
- Felipe Oliveira Carvalho
|
||||
- Felix Gnass
|
||||
- Felix Kling
|
||||
- Fernando Correia
|
||||
- Frankie Bagnardi
|
||||
- François-Xavier Bois
|
||||
- Fred Zhao
|
||||
- G Scott Olson
|
||||
- G. Kay Lee
|
||||
- Gabe Levi
|
||||
- Gareth Nicholson
|
||||
- Garren Smith
|
||||
- Geert Pasteels
|
||||
- Geert-Jan Brits
|
||||
- George A Sisco III
|
||||
- Georgii Dolzhykov
|
||||
- Gilbert
|
||||
- Glen Mailer
|
||||
- Grant Timmerman
|
||||
- Greg Hurrell
|
||||
- Greg Perkins
|
||||
- Greg Roodt
|
||||
- Gregory
|
||||
- Guangqiang Dong
|
||||
- Guido Bouman
|
||||
- Harry Hull
|
||||
- Harry Marr
|
||||
- - Harry Moreno
|
||||
- Harshad Sabne
|
||||
- Hekar Khani
|
||||
- Hendrik Swanepoel
|
||||
- Henrik Nyh
|
||||
- Henry Zhu
|
||||
- Hou Chia
|
||||
- Hugo Jobling
|
||||
- Héliton Nordt
|
||||
- Ian Obermiller
|
||||
- Ignacio Carbajo
|
||||
- Igor Scekic
|
||||
- Ilya Shuklin
|
||||
- Ilyá Belsky
|
||||
- Ingvar Stepanyan
|
||||
- Irae Carvalho
|
||||
- Isaac Salier-Hellendag
|
||||
- Ivan Kozik
|
||||
- Ivan Krechetov
|
||||
- Ivan Vergiliev
|
||||
- J. Andrew Brassington
|
||||
- J. Renée Beach
|
||||
- JD Isaacks
|
||||
- JW
|
||||
- Jack Zhang
|
||||
- Jacob Gable
|
||||
- Jacob Greenleaf
|
||||
- Jae Hun Ro
|
||||
- Jaime Mingo
|
||||
- Jakub Malinowski
|
||||
- James
|
||||
- James Brantly
|
||||
- James Burnett
|
||||
- James Ide
|
||||
- James Long
|
||||
- James Pearce
|
||||
- James Seppi
|
||||
- James South
|
||||
- Jamie Wong
|
||||
- Jamis Charles
|
||||
- Jamison Dance
|
||||
- Jan Hancic
|
||||
- Jan Kassens
|
||||
- Jan Raasch
|
||||
- Jared Forsyth
|
||||
- Jason
|
||||
- Jason Bonta
|
||||
- Jason Ly
|
||||
- Jason Miller
|
||||
- Jason Quense
|
||||
- Jason Trill
|
||||
- Jason Webster
|
||||
- Jay Jaeho Lee
|
||||
- Jean Lauliac
|
||||
- Jed Watson
|
||||
- Jeff Barczewski
|
||||
- Jeff Carpenter
|
||||
- Jeff Chan
|
||||
- Jeff Hicken
|
||||
- Jeff Kolesky
|
||||
- Jeff Morrison
|
||||
- Jeff Welch
|
||||
@@ -158,50 +252,81 @@
|
||||
- Jim Sproch
|
||||
- Jimmy Jea
|
||||
- Jing Chen
|
||||
- Jinwoo Oh
|
||||
- Jiyeon Seo
|
||||
- Joe Stein
|
||||
- Joel Auterson
|
||||
- Johannes Baiter
|
||||
- Johannes Emerich
|
||||
- Johannes Lumpe
|
||||
- John Heroy
|
||||
- John Watson
|
||||
- Jon Beebe
|
||||
- Jon Chester
|
||||
- Jon Hester
|
||||
- Jon Madison
|
||||
- Jon Scott Clark
|
||||
- Jon Tewksbury
|
||||
- Jonas Enlund
|
||||
- Jonas Gebhardt
|
||||
- Jonathan Hsu
|
||||
- Jordan Harband
|
||||
- Jordan Walke
|
||||
- Jorrit Schippers
|
||||
- Joseph Nudell
|
||||
- Joseph Savona
|
||||
- Josh Bassett
|
||||
- Josh Duck
|
||||
- Josh Yudaken
|
||||
- Joshua Go
|
||||
- Joshua Goldberg
|
||||
- Joshua Ma
|
||||
- João Valente
|
||||
- Juan Serrano
|
||||
- Julen Ruiz Aizpuru
|
||||
- Julian Viereck
|
||||
- Julien Bordellier
|
||||
- Jun Wu
|
||||
- Juraj Dudak
|
||||
- Justin Jaffray
|
||||
- Justin Robison
|
||||
- Justin Woo
|
||||
- Kamron Batman
|
||||
- Karl Mikkelsen
|
||||
- Karpich Dmitry
|
||||
- Keito Uchiyama
|
||||
- Kevin Coughlin
|
||||
- Kevin Huang
|
||||
- Kevin Old
|
||||
- KimCoding
|
||||
- Kirk Steven Hansen
|
||||
- Kit Randel
|
||||
- Kohei TAKATA
|
||||
- Koo Youngmin
|
||||
- Kunal Mehta
|
||||
- Kurt Ruppel
|
||||
- Kyle Kelley
|
||||
- Kyle Mathews
|
||||
- Laurence Rowe
|
||||
- Laurent Etiemble
|
||||
- Lee Byron
|
||||
- Lee Jaeyoung
|
||||
- Lei
|
||||
- Leon Fedotov
|
||||
- Leon Yip
|
||||
- Leonardo YongUk Kim
|
||||
- Levi Buzolic
|
||||
- Levi McCallum
|
||||
- Lily
|
||||
- Logan Allen
|
||||
- Luigy Leon
|
||||
- Luke Horvat
|
||||
- MIKAMI Yoshiyuki
|
||||
- Marcin K.
|
||||
- Marcin Kwiatkowski
|
||||
- Marcin Szczepanski
|
||||
- Mariano Desanze
|
||||
- Marjan
|
||||
- Mark Anderson
|
||||
- Mark Funk
|
||||
- Mark Hintz
|
||||
@@ -212,28 +337,49 @@
|
||||
- Martin Andert
|
||||
- Martin Jul
|
||||
- Martin Konicek
|
||||
- Martin Mihaylov
|
||||
- Masaki KOBAYASHI
|
||||
- Mathieu M-Gosselin
|
||||
- Matias Singers
|
||||
- Matsunoki
|
||||
- Matt Brookes
|
||||
- Matt Dunn-Rankin
|
||||
- Matt Harrison
|
||||
- Matt Huggins
|
||||
- Matt Zabriskie
|
||||
- Matthew Dapena-Tretter
|
||||
- Matthew Johnston
|
||||
- Matthew King
|
||||
- Matthew Miner
|
||||
- Matthias Le Brun
|
||||
- Matti Nelimarkka
|
||||
- Max F. Albrecht
|
||||
- Max Heiber
|
||||
- Maxi Ferreira
|
||||
- Maxim Abramchuk
|
||||
- Merrick Christensen
|
||||
- Mert Kahyaoğlu
|
||||
- Michael Chan
|
||||
- Michael Randers-Pehrson
|
||||
- Michael Ridgway
|
||||
- Michael Warner
|
||||
- Michal Srb
|
||||
- Michelle Todd
|
||||
- Mihai Parparita
|
||||
- Mike D Pilsbury
|
||||
- - Mike Groseclose
|
||||
- Mikolaj Dadela
|
||||
- Minwe LUO
|
||||
- Miorel Palii
|
||||
- - Mouad Debbar
|
||||
- Morhaus
|
||||
- Mouad Debbar
|
||||
- Murad
|
||||
- Murray M. Moss
|
||||
- Nadeesha Cabral
|
||||
- Naman Goel
|
||||
- Nate Hunzaker
|
||||
- Nathan White
|
||||
- Neri Marschik
|
||||
- Nicholas Bergson-Shilcock
|
||||
- Nick Fitzgerald
|
||||
- Nick Gavalas
|
||||
@@ -242,14 +388,20 @@
|
||||
- Nick Thompson
|
||||
- Nick Williams
|
||||
- Niklas Boström
|
||||
- Ning Xia
|
||||
- Niole Nelson
|
||||
- Oiva Eskola
|
||||
- Oleg
|
||||
- Oleksii Markhovskyi
|
||||
- Oliver Zeigermann
|
||||
- Olivier Tassinari
|
||||
- Owen Coutts
|
||||
- Pablo Lacerda de Miranda
|
||||
- Paolo Moretti
|
||||
- Pascal Hartig
|
||||
- Patrick Laughlin
|
||||
- Patrick Stapleton
|
||||
- Paul Harper
|
||||
- Paul O’Shannessy
|
||||
- Paul Seiffert
|
||||
- Paul Shen
|
||||
@@ -262,6 +414,7 @@
|
||||
- Petri Lievonen
|
||||
- Pieter Vanderwerff
|
||||
- Pouja Nikray
|
||||
- Prathamesh Sonpatki
|
||||
- Preston Parry
|
||||
- Rafael
|
||||
- Rafal Dittwald
|
||||
@@ -269,76 +422,131 @@
|
||||
- Randall Randall
|
||||
- Ray
|
||||
- Raymond Ha
|
||||
- Reed Loden
|
||||
- Richard D. Worth
|
||||
- Richard Feldman
|
||||
- Richard Kho
|
||||
- Richard Littauer
|
||||
- Richard Livesey
|
||||
- Richard Wood
|
||||
- Rick Beerendonk
|
||||
- Riley Tomasek
|
||||
- Rob Arnold
|
||||
- Robert Knight
|
||||
- Robert Sedovsek
|
||||
- Robin Berjon
|
||||
- Roman Vanesyan
|
||||
- Russ
|
||||
- Ryan Seddon
|
||||
- Sahat Yalkabov
|
||||
- Saif Hakim
|
||||
- Sam Saccone
|
||||
- Sam Selikoff
|
||||
- Samy Al Zahrani
|
||||
- Sander Spies
|
||||
- Scott Burch
|
||||
- Scott Feeney
|
||||
- Sean Kinsey
|
||||
- Sebastian Markbåge
|
||||
- Seoh Char
|
||||
- Serg
|
||||
- Sergey Generalov
|
||||
- Sergey Rubanov
|
||||
- Seyi Adebajo
|
||||
- Shane O'Sullivan
|
||||
- Shaun Trennery
|
||||
- Sheraz
|
||||
- ShihChi Huang
|
||||
- Shim Won
|
||||
- Shota Kubota
|
||||
- Shripad K
|
||||
- Sibi
|
||||
- Simon Højberg
|
||||
- Simon Welsh
|
||||
- Sophia Westwood
|
||||
- Spencer Handley
|
||||
- Stefan Dombrowski
|
||||
- Stephen Murphy
|
||||
- Sterling Cobb
|
||||
- Steve Baker
|
||||
- Steven Luscher
|
||||
- Stoyan Stefanov
|
||||
- Sundeep Malladi
|
||||
- Sunny Juneja
|
||||
- Sven Helmberger
|
||||
- Sverre Johansen
|
||||
- Sébastien Lorber
|
||||
- Sławomir Laskowski
|
||||
- Taeho Kim
|
||||
- Tay Yang Shun
|
||||
- Ted Kim
|
||||
- Teodor Szente
|
||||
- Thomas Aylott
|
||||
- Thomas Boyt
|
||||
- Thomas Reggi
|
||||
- Thomas Röggla
|
||||
- Thomas Shaddox
|
||||
- Thomas Shafer
|
||||
- ThomasCrvsr
|
||||
- Tienchai Wirojsaksaree
|
||||
- Tim Routowicz
|
||||
- Tim Schaub
|
||||
- Timothy Yung
|
||||
- Tobias Reiss
|
||||
- Tom Haggie
|
||||
- Tom Hauburger
|
||||
- Tom MacWright
|
||||
- Tom Occhino
|
||||
- Tomasz Kołodziejski
|
||||
- Tony Spiro
|
||||
- Toru Kobayashi
|
||||
- Trinh Hoang Nhu
|
||||
- Tsung Hung
|
||||
- Tyler Brock
|
||||
- Ustin Zarubin
|
||||
- Vadim Chernysh
|
||||
- Varun Rau
|
||||
- Vasiliy Loginevskiy
|
||||
- Victor Alvarez
|
||||
- Victor Koenders
|
||||
- Ville Immonen
|
||||
- Vincent Riemer
|
||||
- Vincent Siao
|
||||
- Vipul A M
|
||||
- Vitaly Kramskikh
|
||||
- Vjeux
|
||||
- Volkan Unsal
|
||||
- Wayne Larsen
|
||||
- WickyNilliams
|
||||
- Wincent Colaiuta
|
||||
- Wout Mertens
|
||||
- Xavier Morel
|
||||
- XuefengWu
|
||||
- Yakov Dalinchuk
|
||||
- Yasar icli
|
||||
- YouBao Nong
|
||||
- Yuichi Hagio
|
||||
- Yuriy Dybskiy
|
||||
- Yuval Dekel
|
||||
- Zach Bruggeman
|
||||
- Zacharias
|
||||
- arush
|
||||
- brafdlog
|
||||
- chen
|
||||
- clariroid
|
||||
- claudiopro
|
||||
- cutbko
|
||||
- davidxi
|
||||
- dongmeng.ldm
|
||||
- iamchenxin
|
||||
- iamdoron
|
||||
- imagentleman
|
||||
- "Árni Hermann Reynisson"
|
||||
- "张敏"
|
||||
- laiso
|
||||
- li.li
|
||||
- sugarshin
|
||||
- wali-s
|
||||
- yiminghe
|
||||
- youmoo
|
||||
- zhangjg
|
||||
- Árni Hermann Reynisson
|
||||
- 凌恒
|
||||
- 张敏
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Map of short name to more information. `name` will be used but if you don't
|
||||
# want to use your real name, just use whatever. If url is included, your name
|
||||
# will be a link to the provided url.
|
||||
billandjing:
|
||||
name: Bill Fisher and Jing Chen
|
||||
benigeri:
|
||||
name: Paul Benigeri
|
||||
url: https://github.com/benigeri
|
||||
chenglou:
|
||||
name: Cheng Lou
|
||||
url: https://twitter.com/_chenglou
|
||||
@@ -18,8 +19,12 @@ jaredly:
|
||||
jgebhardt:
|
||||
name: Jonas Gebhardt
|
||||
url: https://twitter.com/jonasgebhardt
|
||||
jimandsebastian:
|
||||
name: Jim Sproch and Sebastian Markbåge
|
||||
jimfb:
|
||||
name: Jim Sproch
|
||||
url: http://www.jimsproch.com
|
||||
jingc:
|
||||
name: Jing Chen
|
||||
url: https://twitter.com/jingc
|
||||
josephsavona:
|
||||
name: Joseph Savona
|
||||
url: https://twitter.com/en_JS
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
title: Performance Tools
|
||||
- id: advanced-performance
|
||||
title: Advanced Performance
|
||||
- id: context
|
||||
title: Context
|
||||
- title: Reference
|
||||
items:
|
||||
- id: top-level-api
|
||||
|
||||
@@ -11,11 +11,14 @@
|
||||
<p class="meta">
|
||||
{{ page.date | date: "%B %e, %Y" }}
|
||||
by
|
||||
{% if page.author.url %}
|
||||
<a href="{{page.author.url}}">{{ page.author.name }}</a>
|
||||
{% else %}
|
||||
{{ page.author.name }}
|
||||
{% endif %}
|
||||
{% for author in page.authors %}
|
||||
{% if author.url %}
|
||||
<a href="{{author.url}}">{{ author.name }}</a>
|
||||
{% else %}
|
||||
{{ author.name }}
|
||||
{% endif %}
|
||||
{% if forloop.last == false %} and {% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -7,7 +7,15 @@ module Authors
|
||||
class Generator < Jekyll::Generator
|
||||
def generate(site)
|
||||
site.posts.each do |post|
|
||||
post.data['author'] = site.data['authors'][post['author']]
|
||||
authors = []
|
||||
if post['author'].kind_of?(Array)
|
||||
for author in post['author']
|
||||
authors.push(site.data['authors'][author])
|
||||
end
|
||||
else
|
||||
authors.push(site.data['authors'][post['author']])
|
||||
end
|
||||
post.data['authors'] = authors
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "Flux: An Application Architecture for React"
|
||||
author: fisherwebdevandjing
|
||||
author: [fisherwebdev, jingc]
|
||||
---
|
||||
|
||||
We recently spoke at one of f8's breakout session about Flux, a data flow architecture that works well with React. Check out the video here:
|
||||
|
||||
@@ -40,20 +40,18 @@ The first step is a React `<Story>` component that accepts a `story` prop with t
|
||||
|
||||
```javascript
|
||||
// Story.react.js
|
||||
class Story extends React.Component {
|
||||
export default class Story extends React.Component {
|
||||
render() {
|
||||
var story = this.props.story;
|
||||
return (
|
||||
<View>
|
||||
<Image uri={story.author.profile_picture.uri} />
|
||||
<Image uri={story.author.profilePicture.uri} />
|
||||
<Text>{story.author.name}</Text>
|
||||
<Text>{story.text}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Story;
|
||||
```
|
||||
|
||||
<br/>
|
||||
@@ -66,41 +64,41 @@ Relay automates the process of fetching data for components by wrapping existing
|
||||
// Story.react.js
|
||||
class Story extends React.Component { ... }
|
||||
|
||||
module.exports = Relay.createContainer(Story, {
|
||||
queries: {
|
||||
export default Relay.createContainer(Story, {
|
||||
fragments: {
|
||||
story: /* TODO */
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Before adding the GraphQL query, let's look at the component hierarchy this creates:
|
||||
Before adding the GraphQL fragment, let's look at the component hierarchy this creates:
|
||||
|
||||
<img src="/react/img/blog/relay-components/relay-containers.png" width="397" alt="React Container Data Flow" />
|
||||
|
||||
Most props will be passed through from the container to the original component. However, Relay will return the query results for a prop whenever a query is defined. In this case we'll add a GraphQL query for `story`:
|
||||
Most props will be passed through from the container to the original component. However, Relay will return the query results for a prop whenever a fragment is defined. In this case we'll add a GraphQL fragment for `story`:
|
||||
|
||||
```javascript
|
||||
// Story.react.js
|
||||
class Story extends React.Component { ... }
|
||||
|
||||
module.exports = Relay.createContainer(Story, {
|
||||
queries: {
|
||||
story: graphql`
|
||||
Story {
|
||||
export default Relay.createContainer(Story, {
|
||||
fragments: {
|
||||
story: () => Relay.QL`
|
||||
fragment on Story {
|
||||
author {
|
||||
name,
|
||||
profile_picture {
|
||||
name
|
||||
profilePicture {
|
||||
uri
|
||||
}
|
||||
},
|
||||
}
|
||||
text
|
||||
}
|
||||
`
|
||||
}
|
||||
`,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Queries use ES6 template literals tagged with the `graphql` function. Similar to how JSX transpiles to plain JavaScript objects and function calls, these template literals transpile to plain objects that describe queries. Note that the query's structure closely matches the object structure that we expected in `<Story>`'s render function.
|
||||
Queries use ES6 template literals tagged with the `Relay.QL` function. Similar to how JSX transpiles to plain JavaScript objects and function calls, these template literals transpile to plain objects that describe fragments. Note that the fragment's structure closely matches the object structure that we expected in `<Story>`'s render function.
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -112,7 +110,7 @@ We can render a Relay component by providing Relay with the component (`<Story>`
|
||||
{
|
||||
author: {
|
||||
name: "Greg",
|
||||
profile_picture: {
|
||||
profilePicture: {
|
||||
uri: "https://…"
|
||||
}
|
||||
},
|
||||
@@ -159,35 +157,35 @@ module.exports = NewsFeed;
|
||||
|
||||
`<NewsFeed>` has two new requirements: it composes `<Story>` and requests more data at runtime.
|
||||
|
||||
Just as React views can be nested, Relay queries can compose queries from child components. Composition in GraphQL uses ES6 template literal substitution: `${Component.getQuery('prop')}`. Pagination can be accomplished with a query parameter, specified with `<param>` (as in `stories(first: <count>)`):
|
||||
Just as React views can be nested, Relay components can compose query fragments from child components. Composition in GraphQL uses ES6 template literal substitution: `${Component.getFragment('prop')}`. Pagination can be accomplished with a variable, specified with `$variable` (as in `stories(first: $count)`):
|
||||
|
||||
```javascript
|
||||
// NewsFeed.react.js
|
||||
class NewsFeed extends React.Component { ... }
|
||||
|
||||
module.exports = Relay.createContainer(NewsFeed, {
|
||||
queryParams: {
|
||||
count: 3 /* default to 3 stories */
|
||||
export default Relay.createContainer(NewsFeed, {
|
||||
initialVariables: {
|
||||
count: 3 /* default to 3 stories */
|
||||
},
|
||||
queries: {
|
||||
viewer: graphql`
|
||||
Viewer {
|
||||
stories(first: <count>) { /* fetch viewer's stories */
|
||||
edges { /* traverse the graph */
|
||||
fragments: {
|
||||
viewer: () => Relay.QL`
|
||||
fragment on Viewer {
|
||||
stories(first: $count) { /* fetch viewer's stories */
|
||||
edges { /* traverse the graph */
|
||||
node {
|
||||
${Story.getQuery('story')} /* compose child query */
|
||||
${Story.getFragment('story')} /* compose child fragment */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
`,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Whenever `<NewsFeed>` is rendered, Relay will recursively expand all the composed queries and fetch them in a single trip to the server. In this case, the `text` and `author` data will be fetched for each of the 3 story nodes.
|
||||
Whenever `<NewsFeed>` is rendered, Relay will recursively expand all the composed fragments and fetch the queries in a single trip to the server. In this case, the `text` and `author` data will be fetched for each of the 3 story nodes.
|
||||
|
||||
Query parameters are available to components as `props.queryParams` and can be modified with `props.setQueryParams(nextParams)`. We can use these to implement pagination:
|
||||
Query variables are available to components as `props.relay.variables` and can be modified with `props.relay.setVariables(nextVariables)`. We can use these to implement pagination:
|
||||
|
||||
```javascript
|
||||
// NewsFeed.react.js
|
||||
@@ -196,16 +194,16 @@ class NewsFeed extends React.Component {
|
||||
|
||||
loadMore() {
|
||||
// read current params
|
||||
var count = this.props.queryParams.count;
|
||||
var count = this.props.relay.variables.count;
|
||||
// update params
|
||||
this.props.setQueryParams({
|
||||
count: count + 5
|
||||
this.props.relay.setVariables({
|
||||
count: count + 5,
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now when `loadMore()` is called, Relay will send a GraphQL request for the additional five stories. When these stories are fetched, the component will re-render with the new stories available in `props.viewer.stories` and the updated count reflected in `props.queryParams.count`.
|
||||
Now when `loadMore()` is called, Relay will send a GraphQL request for the additional five stories. When these stories are fetched, the component will re-render with the new stories available in `props.viewer.stories` and the updated count reflected in `props.relay.variables.count`.
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ We believe there are a number of weakness in typical REST systems, ones that are
|
||||
|
||||
* Fetching complicated object graphs require multiple round trips between the client and server to render single views. For mobile applications operating in variable network conditions, these multiple roundtrips are highly undesirable.
|
||||
* Invariably fields and additional data are added to REST endpoints as the system requirements change. However, old clients also receive this additional data as well, because the data fetching specification is encoded on the server rather than the client. As result, these payloads tend to grow over time for all clients. When this becomes a problem for a system, one solution is to overlay a versioning system onto the REST endpoints. Versioning also complicates a server, and results in code duplication, spaghetti code, or a sophisticated, hand-rolled infrastructure to manage it. Another solution to limit over-fetching is to provide multiple views – such as “compact” vs “full” – of the same REST endpoint, however this coarse granularity often does not offer adequate flexibility.
|
||||
* REST endpoints are usually weakly-typed and lack machine-readable metadata. While there is much debate about the merits of strong- versus weak-typing in distributed systems, we believe in strong typing because of the correctness guarantees and tooling opportunities it provides. Developer deal with systems that lack this metadata by inspecting frequently out-of-date documentation and then writing code against the documentation.
|
||||
* REST endpoints are usually weakly-typed and lack machine-readable metadata. While there is much debate about the merits of strong- versus weak-typing in distributed systems, we believe in strong typing because of the correctness guarantees and tooling opportunities it provides. Developers deal with systems that lack this metadata by inspecting frequently out-of-date documentation and then writing code against the documentation.
|
||||
* Many of these attributes are linked to the fact that “REST is intended for long-lived network-based applications that span multiple organizations” [according to its inventor](http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven). This is not a requirement for APIs that serve a client app built within the same organization.
|
||||
|
||||
Nearly all externally facing REST APIs we know of trend or end up in these non-ideal states, as well as nearly all *internal* REST APIs. The consequences of opaqueness and over-fetching are more severe in internal APIs since their velocity of change and level of usage is almost always higher.
|
||||
@@ -90,7 +90,7 @@ Because of multiple round-trips and over-fetching, applications built in the RES
|
||||
Many applications have no formalized client-server contract. Product developers access server capabilities through *ad hoc* endpoints and write custom code to fetch the data they need. Servers define procedures, and they return data. This approach has the virtue of simplicity, but can often become untenable as systems age.
|
||||
|
||||
* These systems typically define a custom endpoint per view. For systems with a wide surface area this can quickly grow into a maintenance nightmare of orphaned endpoints, inconsistent tooling, and massive server code duplication. Disciplined engineering organizations can mitigate these issues with great engineering practices, high quality abstractions, and custom tooling. However, given our experience we believe that custom endpoints tend to lead to entropic server codebases.
|
||||
* Much like REST, the payloads of custom endpoints grow monotonically (even with mitigation from versioning systems) as the server evolves. Deployed clients cannot break, and, with rapid release cycles and backwards compatibility guarantees, distributed applications will have large numbers of extant versions. Under these constraints it is difficult remove data from a custom endpoint.
|
||||
* Much like REST, the payloads of custom endpoints grow monotonically (even with mitigation from versioning systems) as the server evolves. Deployed clients cannot break, and, with rapid release cycles and backwards compatibility guarantees, distributed applications will have large numbers of extant versions. Under these constraints it is difficult to remove data from a custom endpoint.
|
||||
* Custom endpoints tend to – for a client developer – create a clunky, multi-language, multi-environment development process. No matter if the data has been accessed before in a different view, they are required to first change the custom endpoint, then deploy that code to a server accessible from a mobile device, and only then change the client to utilize that data. In GraphQL – unless the data in the view is completely new to the entire system – a product developer adds a field to a GraphQL query and the work on the client continues unabated.
|
||||
* Much like REST, most systems with custom endpoints do not have a formalized type system, which eliminates the possibility for the tools and guarantees that introspective type systems can provide. Some custom-endpoint-driven systems do use a strongly typed serialization scheme, such as Protocol Buffers, Thrift, or XML. Those do allow for direct parsing of responses into typed classes and eliminating boilerplate shuffling from JSON into handwritten classes. These systems are as not as expressive and flexible as GraphQL, and the other downsides of *ad hoc* endpoints remain.
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ These builds are also available in the `react` package on bower.
|
||||
ReactDOM.render(<MyComponent />, node);
|
||||
```
|
||||
|
||||
We’ve published the [automated codemod script](https://github.com/facebook/react/blob/master/packages/react-codemod/README.md) we used at Facebook to help you with this transition.
|
||||
We’ve published the [automated codemod script](https://github.com/reactjs/react-codemod/blob/master/README.md) we used at Facebook to help you with this transition.
|
||||
|
||||
The add-ons have moved to separate packages as well: `react-addons-clone-with-props`, `react-addons-create-fragment`, `react-addons-css-transition-group`, `react-addons-linked-state-mixin`, `react-addons-perf`, `react-addons-pure-render-mixin`, `react-addons-shallow-compare`, `react-addons-test-utils`, `react-addons-transition-group`, and `react-addons-update`, plus `ReactDOM.unstable_batchedUpdates` in `react-dom`.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "ReactDOM.render and the Top Level React API"
|
||||
author: jimandsebastian
|
||||
author: ["jimfb", "sebmarkbage"]
|
||||
---
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ Like always, we have a few breaking changes in this release. We know changes can
|
||||
|
||||
If your code is free of warnings when running under React 0.13, upgrading should be easy. We have two new small breaking changes that didn't give a warning in 0.13 (see below). Every new change in 0.14, including the major changes below, is introduced with a runtime warning and will work as before until 0.15, so you don't have to worry about your app breaking with this upgrade.
|
||||
|
||||
For the two major changes which require significant code changes, we've included [codemod scripts](https://github.com/reactjs/react-codemod/blob/master/README.md) to help you upgrade your code automatically.
|
||||
|
||||
See the changelog below for more details.
|
||||
|
||||
## Installation
|
||||
@@ -64,7 +66,7 @@ If you can’t use `npm` yet, we provide pre-built browser builds for your conve
|
||||
ReactDOM.render(<MyComponent />, node);
|
||||
```
|
||||
|
||||
The old names will continue to work with a warning until 0.15 is released, and we’ve published the [automated codemod script](https://github.com/facebook/react/blob/master/packages/react-codemod/README.md) we used at Facebook to help you with this transition.
|
||||
The old names will continue to work with a warning until 0.15 is released, and we’ve published the [automated codemod script](https://github.com/reactjs/react-codemod/blob/master/README.md) we used at Facebook to help you with this transition.
|
||||
|
||||
The add-ons have moved to separate packages as well:
|
||||
- `react-addons-clone-with-props`
|
||||
@@ -99,7 +101,7 @@ If you can’t use `npm` yet, we provide pre-built browser builds for your conve
|
||||
```
|
||||
|
||||
This change also applies to the return result of `ReactDOM.render` when passing a DOM node as the top component. As with refs, this change does not affect custom components.
|
||||
|
||||
|
||||
With this change, we’re deprecating `.getDOMNode()` and replacing it with `ReactDOM.findDOMNode` (see below). If your components are currently using `.getDOMNode()`, they will continue to work with a warning until 0.15.
|
||||
|
||||
- #### Stateless functional components
|
||||
@@ -124,7 +126,7 @@ If you can’t use `npm` yet, we provide pre-built browser builds for your conve
|
||||
```
|
||||
|
||||
These components behave just like a React class with only a `render` method defined. Since no component instance is created for a functional component, any `ref` added to one will evaluate to `null`. Functional components do not have lifecycle methods, but you can set `.propTypes` and `.defaultProps` as properties on the function.
|
||||
|
||||
|
||||
This pattern is designed to encourage the creation of these simple components that should comprise large portions of your apps. In the future, we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations.
|
||||
|
||||
- #### Deprecation of react-tools
|
||||
@@ -133,7 +135,7 @@ If you can’t use `npm` yet, we provide pre-built browser builds for your conve
|
||||
|
||||
- #### Compiler optimizations
|
||||
|
||||
React now supports two compiler optimizations that can be enabled in Babel 5.8.23 and newer. Both of these transforms **should be enabled only in production** (e.g., just before minifying your code) because although they improve runtime performance, they make warning messages more cryptic and skip important checks that happen in development mode, including propTypes.
|
||||
React now supports two compiler optimizations that can be enabled in Babel 5.8.24 and newer. Both of these transforms **should be enabled only in production** (e.g., just before minifying your code) because although they improve runtime performance, they make warning messages more cryptic and skip important checks that happen in development mode, including propTypes.
|
||||
|
||||
**Inlining React elements:** The `optimisation.react.inlineElements` transform converts JSX elements to object literals like `{type: 'div', props: ...}` instead of calls to `React.createElement`.
|
||||
|
||||
@@ -159,7 +161,7 @@ Each of these changes will continue to work as before with a new warning until t
|
||||
|
||||
- Due to the DOM node refs change mentioned above, `this.getDOMNode()` is now deprecated and `ReactDOM.findDOMNode(this)` can be used instead. Note that in most cases, calling `findDOMNode` is now unnecessary – see the example above in the “DOM node refs” section.
|
||||
|
||||
With each returned DOM node, we've added a `getDOMNode` method for backwards compatibility that will work with a warning until 0.15. If you have a large codebase, you can use our [automated codemod script](https://github.com/facebook/react/blob/master/packages/react-codemod/README.md) to change your code automatically.
|
||||
With each returned DOM node, we've added a `getDOMNode` method for backwards compatibility that will work with a warning until 0.15. If you have a large codebase, you can use our [automated codemod script](https://github.com/reactjs/react-codemod/blob/master/README.md) to change your code automatically.
|
||||
|
||||
- `setProps` and `replaceProps` are now deprecated. Instead, call ReactDOM.render again at the top level with the new props.
|
||||
- ES6 component classes must now extend `React.Component` in order to enable stateless function components. The [ES3 module pattern](/react/blog/2015/01/27/react-v0.13.0-beta-1.html#other-languages) will continue to work.
|
||||
|
||||
86
docs/_posts/2015-10-19-reactiflux-is-moving-to-discord.md
Normal file
86
docs/_posts/2015-10-19-reactiflux-is-moving-to-discord.md
Normal file
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: "Reactiflux is moving to Discord"
|
||||
author: benigeri
|
||||
---
|
||||
|
||||
TL;DR: Slack decided that Reactiflux had too many members and disabled new invites. Reactiflux is moving to Discord. Join us: [http://join.reactiflux.com](http://join.reactiflux.com/)
|
||||
|
||||
## What happened with Slack?
|
||||
|
||||
A few weeks ago, Reactiflux reached 7,500 members on Slack. Shortly after, Slack decided we were too big and disabled invites. There was no way for new users to join. Many of us were sad and upset. We loved Slack. Our community was built around it.
|
||||
|
||||
We reached out to Slack several times, but their decision was firm. Our large community caused performance issues. Slack wants to focus on building a great product for teams, not necessarily large open communities. Losing focus and building for too many use cases always leads to product bloat, and eventually a decrease in quality.
|
||||
|
||||
## So… why Discord?
|
||||
|
||||
After a [long and thorough debate](https://github.com/reactiflux/volunteers/issues/25), Discord quickly emerged as the most promising service. After just a few days, 400 members had joined the Discord server, and many already loved it.
|
||||
|
||||
### Easiest to join
|
||||
|
||||
Discord is the easiest platform to join. New users can immediately join our conversations without having to create an account. All they need to do is provide a name. No permission granting, no password, no email confirmation.
|
||||
|
||||
This is critically useful for us, and will make Reactiflux even more open and accessible.
|
||||
|
||||
### Great apps
|
||||
|
||||
Out of all of the services we’ve tried, Discord’s apps are by far the most polished. They are well designed, easy to use, and surprisingly fast. In addition to the web app, they have mobile apps on both iOS and Android as well as desktop apps for OS X and Windows, with Linux support coming soon.
|
||||
|
||||
Their desktop apps are built with React and Electron, and their iOS app is built with React Native.
|
||||
|
||||
### Moderation tools
|
||||
|
||||
So far, we’ve been fortunate not to have to deal with spammers and trolls. As our community continues to grow, that might change. Unsurprisingly, Discord is the only app we’ve seen with legitimate moderation tools. It was built for gaming communities, after all.
|
||||
|
||||
### Great multiple Server support
|
||||
|
||||
Your Discord account works with every Discord server, which is the equivalent of a Slack team. You don’t need to create a new account every time you join a new team. You can join new servers in one click, and it’s very easy to switch between them. Discord messages also work across servers, so your personal conversations are not scoped to a single server.
|
||||
|
||||
Instead of having one huge, crowded Reactiflux server, we can branch off closely related channels into sub-servers. Communities will start overlapping, and it will be easy to interact with non-Reactiflux channels.
|
||||
|
||||
### It’s hosted
|
||||
|
||||
Self-hosted apps require maintenance. We’re all busy, and we can barely find the time to keep our landing page up to date and running smoothly. More than anything, we need a stable platform, and we don’t have the resources to guarantee that right now.
|
||||
|
||||
It’s a much safer bet to offload the hosting to Discord, who is already keeping the lights on for all their users.
|
||||
|
||||
### We like the team
|
||||
|
||||
And they seem to like us back. They are excited for us to join them, and they’ve been very responsive to our feedback and suggestions.
|
||||
|
||||
They implemented code syntax highlighting just a few days after we told them we needed it.
|
||||
|
||||
Discord’s team has already built a solid suite of apps, and they have shown us how much they care about their users. We’re excited to see how they will continue to improve their product.
|
||||
|
||||
## And what’s the catch?
|
||||
|
||||
Choosing the best chat service is subjective. There are a million reasons why Discord *might be* a terrible idea. Here are the ones that we’re most worried about:
|
||||
|
||||
### Difficult channel management
|
||||
|
||||
Channel management seems to be the biggest issue. There is no way to opt out of channels; you can only mute them. And you can only mute channels one by one. There is no way to star channels, and channels can only be sorted on the server level. Each user will see the list of channels in the same order.
|
||||
|
||||
As the number of channels grow, it will be challenging to keep things in order. Branching off sub-servers will help, and we will keep an easily accessible directory of channels across our main server and all of the sub-servers.
|
||||
|
||||
We can build simple tools to make channel lookup easier, and the Discord team is working on improvements that should make this more manageable.
|
||||
|
||||
### No Search
|
||||
|
||||
Lack of search is clearly a bummer, but Discord is working on it. Search is coming!
|
||||
|
||||
### Firewall
|
||||
|
||||
A couple of users aren’t able to access Discord at work since other corporate filters classify it as a gaming application. This sucks, but it seems to be a rare case. So far, it seems only to affect 0.6% of our current community (3/500).
|
||||
|
||||
We hope that these users can get Discord's domains whitelisted, and we’ll try to find a solution if this is a widespread issue. The Discord team is aware of the issue as well.
|
||||
|
||||
## Is Discord going to disappear tomorrow?
|
||||
|
||||
Probably not tomorrow. They have 14 people [full time](https://discordapp.com/company), and they’ve raised money from some of the best investors in Silicon Valley, including [Benchmark](http://www.benchmark.com/) and [Accel](http://www.accel.com/companies/).
|
||||
|
||||
By focusing on gaming communities, Discord has differentiated itself from the many other communication apps. Discord is well received and has a rapidly growing user base. They plan to keep their basic offerings free for unlimited users and hope to make money with premium offerings (themes, add-ons, content, and more).
|
||||
|
||||
## Join us!
|
||||
|
||||
More than 500 of us have already migrated to the new Reactiflux. Join us, we're one click away: [http://join.reactiflux.com](http://join.reactiflux.com/)
|
||||
|
||||
*Note: Jordan Hawker’s thorough [research](http://jhawk.co/team-chat-comparison) made our decision a lot easier.*
|
||||
40
docs/_posts/2015-10-28-react-v0.14.1.md
Normal file
40
docs/_posts/2015-10-28-react-v0.14.1.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "React v0.14.1"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
After a couple weeks of having more people use v0.14, we're ready to ship a patch release addressing a few issues. Thanks to everybody who has reported issues and written patches!
|
||||
|
||||
The release is now available for download:
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-0.14.1.js>
|
||||
Minified build for production: <https://fb.me/react-0.14.1.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-0.14.1.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-0.14.1.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-0.14.1.js>
|
||||
Minified build for production: <https://fb.me/react-dom-0.14.1.min.js>
|
||||
|
||||
We've also published version `0.14.1` of the `react`, `react-dom`, and addons packages on npm and the `react` package on bower.
|
||||
|
||||
- - -
|
||||
|
||||
## Changelog
|
||||
|
||||
### React DOM
|
||||
- Fixed bug where events wouldn't fire in old browsers when using React in development mode
|
||||
- Fixed bug preventing use of `dangerouslySetInnerHTML` with Closure Compiler Advanced mode
|
||||
- Added support for `srcLang`, `default`, and `kind` attributes for `<track>` elements
|
||||
- Added support for `color` attribute
|
||||
- Ensured legacy `.props` access on DOM nodes is updated on re-renders
|
||||
|
||||
### React TestUtils Add-on
|
||||
- Fixed `scryRenderedDOMComponentsWithClass` so it works with SVG
|
||||
|
||||
### React CSSTransitionGroup Add-on
|
||||
- Fix bug preventing `0` to be used as a timeout value
|
||||
|
||||
### React on Bower
|
||||
- Added `react-dom.js` to `main` to improve compatibility with tooling
|
||||
31
docs/_posts/2015-11-02-react-v0.14.2.md
Normal file
31
docs/_posts/2015-11-02-react-v0.14.2.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
title: "React v0.14.2"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
We have a quick update following the release of 0.14.1 last week. It turns out we broke a couple things in the development build of React when using Internet Explorer. Luckily it was only the development build, so your production applications were unaffected. This release is mostly to address those issues. There is one notable change if consuming React from npm. For the `react-dom` package, we moved `react` from a regular dependency to a peer dependency. This will impact very few people as these two are typically installed together at the top level, but it will fix some issues with dependencies of installed components also using `react` as a peer dependency.
|
||||
|
||||
The release is now available for download:
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-0.14.2.js>
|
||||
Minified build for production: <https://fb.me/react-0.14.2.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-0.14.2.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-0.14.2.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-0.14.2.js>
|
||||
Minified build for production: <https://fb.me/react-dom-0.14.2.min.js>
|
||||
|
||||
We've also published version `0.14.2` of the `react`, `react-dom`, and addons packages on npm and the `react` package on bower.
|
||||
|
||||
- - -
|
||||
|
||||
## Changelog
|
||||
|
||||
### React DOM
|
||||
- Fixed bug with development build preventing events from firing in some versions of Internet Explorer & Edge
|
||||
- Fixed bug with development build when using es5-sham in older versions of Internet Explorer
|
||||
- Added support for `integrity` attribute
|
||||
- Fixed bug resulting in `children` prop being coerced to a string for custom elements, which was not the desired behavior.
|
||||
- Moved `react` from `dependencies` to `peerDependencies` to match expectations and align with `react-addons-*` packages
|
||||
@@ -9,7 +9,12 @@ id: all-posts
|
||||
<div class="inner-content">
|
||||
<h1>All Posts</h1>
|
||||
{% for page in site.posts %}
|
||||
<p><strong><a href="/react{{ page.url }}">{{ page.title }}</a></strong> on {{ page.date | date: "%B %e, %Y" }} by {{ page.author.name }}</p>
|
||||
<p><strong><a href="/react{{ page.url }}">{{ page.title }}</a></strong> on {{ page.date | date: "%B %e, %Y" }} by
|
||||
{% for author in page.authors %}
|
||||
{{ author.name }}
|
||||
{% if forloop.last == false %} and {% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -390,6 +390,38 @@ h1, h2, h3, h4, h5, h6 {
|
||||
@include clearfix;
|
||||
}
|
||||
|
||||
/* JSX Compiler */
|
||||
|
||||
.jsxCompiler {
|
||||
margin: 0 auto;
|
||||
padding-top: 20px;
|
||||
width: 1220px;
|
||||
|
||||
label.compiler-option {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
#jsxCompiler {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.playgroundPreview {
|
||||
padding: 0;
|
||||
width: 600px;
|
||||
|
||||
pre {
|
||||
@include code-typography;
|
||||
}
|
||||
}
|
||||
|
||||
.playgroundError {
|
||||
// The compiler view kills padding in order to render the CodeMirror code
|
||||
// more nicely. For the error view, put a padding back
|
||||
padding: 15px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-prev {
|
||||
float: left;
|
||||
}
|
||||
|
||||
28
docs/docs/01-why-react.de-DE.md
Normal file
28
docs/docs/01-why-react.de-DE.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
id: why-react-de-DE
|
||||
title: Warum React?
|
||||
permalink: why-react-de-DE.html
|
||||
---
|
||||
React ist eine JavaScript-Bibliothek von Facebook und Instagram für Benutzeroberflächen. Man kann sich React als das **V** in **[MVC](https://de.wikipedia.org/wiki/Model_View_Controller)** vorstellen.
|
||||
|
||||
Wir haben React für folgende Aufgabe entwickelt: **umfangreiche Anwendungen zu bauen, deren Daten sich zeitlich ändern**.
|
||||
|
||||
## Einfach
|
||||
|
||||
Beschreibe, wie sich Deine App zu jedem gewünschten Zeitpunkt präsentieren soll und React kümmert sich um alle Benutzeroberflächen-Änderungen sobald sich die zugrundeliegenden Daten ändern.
|
||||
|
||||
## Deklarativ
|
||||
|
||||
Bei Datenveränderungen drückt React bildlich die "Aktualisieren"-Taste und versteht sich darauf, nur die veränderten Elemente zu erneuern.
|
||||
|
||||
## Baue zusammensetzbare Komponenten
|
||||
|
||||
React unterstützt die Entwicklung wiederverwendbarer Komponenten. Tatsächlich machst Du in React nichts anderes, als Komponenten zu bauen. Dank ihrer Kapselung erleichtern Komponenten die Wiederverwendung und das Testen von Code sowie die Trennung der Belange.
|
||||
|
||||
## Gib' ihnen fünf Minuten
|
||||
|
||||
React hinterfragt eine ganze Reihe konventioneller Standpunkte. Auf den ersten Blick mögen einige Ideen verrückt klingen. [Gib' ihnen fünf Minuten](https://signalvnoise.com/posts/3124-give-it-five-minutes) während Du diese Anleitung liest; diese verrückten Ideen halfen dabei, tausende von Komponenten innerhalb und außerhalb von Facebook und Instagram zu entwickeln.
|
||||
|
||||
## Erfahre mehr
|
||||
|
||||
Erfahre mehr über unsere Motivation zur Entwicklung von React in [diesem Blogeintrag](/react/blog/2013/06/05/why-react.html).
|
||||
@@ -5,13 +5,13 @@ permalink: why-react-zh-CN.html
|
||||
next: displaying-data-zh-CN.html
|
||||
---
|
||||
|
||||
React 是一个 Facebook 和 Instagram 用来创建用户界面的 JavaScript 库。很人多认为 React 是 **[MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)** 中的 **V**(视图)。
|
||||
React 是一个 Facebook 和 Instagram 用来创建用户界面的 JavaScript 库。很多人选择将 React 认为是 **[MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)** 中的 **V**(视图)。
|
||||
|
||||
我们创造 React 是为了解决一个问题:**构建随着时间数据不断变化的大规模应用程序**。
|
||||
|
||||
### 简单
|
||||
|
||||
仅仅只要表达出你的应用程序在任一个时间点应该长的样子,然后当底层的数据变了,React 会自动处理所有用户界面的更新。
|
||||
仅仅只要表达出你的应用程序在任一个时间点应该呈现的样子,然后当底层的数据变了,React 会自动处理所有用户界面的更新。
|
||||
|
||||
### 声明式 (Declarative)
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ next: jsx-in-depth.html
|
||||
|
||||
The most basic thing you can do with a UI is display some data. React makes it easy to display data and automatically keeps the interface up-to-date when the data changes.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
Let's look at a really simple example. Create a `hello-react.html` file with the following code:
|
||||
@@ -20,6 +19,7 @@ Let's look at a really simple example. Create a `hello-react.html` file with the
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
@@ -55,7 +55,6 @@ setInterval(function() {
|
||||
}, 500);
|
||||
```
|
||||
|
||||
|
||||
## Reactive Updates
|
||||
|
||||
Open `hello-react.html` in a web browser and type your name into the text field. Notice that React is only changing the time string in the UI — any input you put in the text field remains, even though you haven't written any code to manage this behavior. React figures it out for you and does the right thing.
|
||||
@@ -64,7 +63,6 @@ The way we are able to figure this out is that React does not manipulate the DOM
|
||||
|
||||
The inputs to this component are called `props` — short for "properties". They're passed as attributes in JSX syntax. You should think of these as immutable within the component, that is, **never write to `this.props`**.
|
||||
|
||||
|
||||
## Components are Just Like Functions
|
||||
|
||||
React components are very simple. You can think of them as simple functions that take in `props` and `state` (discussed later) and render HTML. With this in mind, components are easy to reason about.
|
||||
@@ -73,7 +71,6 @@ React components are very simple. You can think of them as simple functions that
|
||||
>
|
||||
> **One limitation**: React components can only render a single root node. If you want to return multiple nodes they *must* be wrapped in a single root.
|
||||
|
||||
|
||||
## JSX Syntax
|
||||
|
||||
We strongly believe that components are the right way to separate concerns rather than "templates" and "display logic." We think that markup and the code that generates it are intimately tied together. Additionally, display logic is often very complex and using template languages to express it becomes cumbersome.
|
||||
@@ -98,7 +95,6 @@ JSX is similar to HTML, but not exactly the same. See [JSX gotchas](/react/docs/
|
||||
|
||||
[Babel exposes a number of ways to get started using JSX](http://babeljs.io/docs/setup/), ranging from command line tools to Ruby on Rails integrations. Choose the tool that works best for you.
|
||||
|
||||
|
||||
## React without JSX
|
||||
|
||||
JSX is completely optional; you don't have to use JSX with React. You can create React elements in plain JavaScript using `React.createElement`, which takes a tag name or component, a properties object, and variable number of optional child arguments.
|
||||
|
||||
@@ -21,6 +21,7 @@ next: jsx-in-depth-zh-CN.html
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
@@ -95,16 +96,16 @@ JSX 非常小;上面“hello, world”的例子使用了 JSX 所有的特性
|
||||
|
||||
JSX 类似于 HTML,但不是完全一样。参考 [JSX 陷阱](/react/docs/jsx-gotchas-zh-CN.html) 学习关键区别。
|
||||
|
||||
最简单开始学习 JSX 的方法就是使用浏览器端的 `JSXTransformer`。我们强烈建议你不要在生产环境中使用它。你可以通过我们的命令行工具 [react-tools](https://www.npmjs.com/package/react-tools) 包来预编译你的代码。
|
||||
|
||||
[Babel 公开了一些使用 JSX 的方式],从命令行工具到 Ruby on Rails 集成。选择一个对你来说最合适的工具。
|
||||
|
||||
## 没有 JSX 的 React
|
||||
|
||||
你完全可以选择是否使用 JSX,并不是 React 必须的。你可以通过 `React.createElement` 来创建一个树。第一个参数是标签,第二个参数是一个属性对象,每三个是子节点。
|
||||
JSX完全是可选的;你无需在 React 中必须使用 JSX。你可以通过 `React.createElement` 来创建一个树。第一个参数是标签,第二个参数是一个属性对象,每三个是子节点。
|
||||
|
||||
```javascript
|
||||
var child = React.createElement('li', null, 'Text Content');
|
||||
var root = React.createElement('ul', { className: 'my-list' }, child);
|
||||
var child1 = React.createElement('li', null, 'First Text Content');
|
||||
var child2 = React.createElement('li', null, 'Second Text Content');
|
||||
var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
|
||||
ReactDOM.render(root, document.getElementById('example'));
|
||||
```
|
||||
|
||||
@@ -121,6 +122,7 @@ React 已经为 HTML 标签提供内置工厂方法。
|
||||
|
||||
```javascript
|
||||
var root = React.DOM.ul({ className: 'my-list' },
|
||||
React.DOM.li(null, 'Text Content')
|
||||
);
|
||||
React.DOM.li(null, 'Text Content')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
@@ -216,4 +216,4 @@ var content = (
|
||||
```
|
||||
|
||||
> 注意:
|
||||
> JSXはHTMLに似ていますが、全く同じではありません。いくつかのキーの違いについては[JSXの理解](/react/docs/jsx-gotchas.html) をご覧ください。
|
||||
> JSXはHTMLに似ていますが、全く同じではありません。いくつかのキーの違いについては[JSXの理解](/react/docs/jsx-gotchas.html) をご覧ください。
|
||||
|
||||
@@ -22,7 +22,7 @@ It doesn't alter the semantics of JavaScript.
|
||||
|
||||
React can either render HTML tags (strings) or React components (classes).
|
||||
|
||||
To render a HTML tag, just use lower-case tag names in JSX:
|
||||
To render an HTML tag, just use lower-case tag names in JSX:
|
||||
|
||||
```javascript
|
||||
var myDivElement = <div className="foo" />;
|
||||
|
||||
@@ -99,7 +99,7 @@ var Nav = React.createClass({displayName: "Nav", });
|
||||
如果你正在构建一个有很多子组件的组件,比如表单,你也许会最终得到许多的变量声明。
|
||||
|
||||
```javascript
|
||||
// 尴尬的变量声明块
|
||||
// 尴尬的变量声明块
|
||||
var Form = MyFormComponent;
|
||||
var FormRow = Form.Row;
|
||||
var FormLabel = Form.Label;
|
||||
@@ -221,5 +221,5 @@ var content = (
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>
|
||||
> JSX 类似于 HTML,但不完全一样。参考 [JSX 陷阱](/react/docs/jsx-gotchas-zh-CN.html) 了解主要不同。
|
||||
|
||||
@@ -12,7 +12,7 @@ If you know all the properties that you want to place on a component ahead of ti
|
||||
var component = <Component foo={x} bar={y} />;
|
||||
```
|
||||
|
||||
## Mutating Props is Bad, mkay
|
||||
## Mutating Props is Bad
|
||||
|
||||
If you don't know which properties you want to set, you might be tempted to add them onto the object later:
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ If you want to display an HTML entity within dynamic content, you will run into
|
||||
<div>{'First · Second'}</div>
|
||||
```
|
||||
|
||||
There are various ways to work-around this issue. The easiest one is to write unicode characters directly in JavaScript. You need to make sure that the file is saved as UTF-8 and that the proper UTF-8 directives are set so the browser will display it correctly.
|
||||
There are various ways to work-around this issue. The easiest one is to write Unicode characters directly in JavaScript. You need to make sure that the file is saved as UTF-8 and that the proper UTF-8 directives are set so the browser will display it correctly.
|
||||
|
||||
```javascript
|
||||
<div>{'First · Second'}</div>
|
||||
|
||||
@@ -78,7 +78,7 @@ Reactがデータの変更を通知する共通な方法は `setState(data, call
|
||||
|
||||
`this.state` UIのstateを表す必要がある最小限の量のデータだけを保持するべきです。このような点で以下のようなものは保持するべきではありません。
|
||||
|
||||
* **計算されたデータ:**
|
||||
* **計算されたデータ:**
|
||||
stateに基づく事前に計算された値について心配は要りません。 `render()` を用いて、全ての計算を行って、UIの一貫性を保証するよりも簡単です。例えば、stateにリスト化されたアイテムの配列を持っていて、文字列としてその数をレンダリングしたいとして、それらをstateに保持するよりも `render()` メソッドに `this.state.listItems.length + ' list items'` を単純にレンダリングすれば良いのです。
|
||||
* **Reactのコンポーネント:** 隠れたpropsとstateに基づいて `render()` でそれらをビルドしてください。
|
||||
* **propsからコピーしたデータ:** 可能であれば、propsを真のソースとして使ってみてください。propsは時とともに変化し得るので、正しくstateにpropsを保持する使い方は、以前の値を知っていることになり得ます。
|
||||
* **propsからコピーしたデータ:** 可能であれば、propsを真のソースとして使ってみてください。propsは時とともに変化し得るので、正しくstateにpropsを保持する使い方は、以前の値を知っていることになり得ます。
|
||||
|
||||
@@ -8,7 +8,6 @@ next: multiple-components.html
|
||||
|
||||
You've already [learned how to display data](/react/docs/displaying-data.html) with React. Now let's look at how to make our UIs interactive.
|
||||
|
||||
|
||||
## A Simple Example
|
||||
|
||||
```javascript
|
||||
@@ -35,12 +34,10 @@ 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.
|
||||
|
||||
|
||||
## Under the Hood: Autobinding and Event Delegation
|
||||
|
||||
Under the hood, React does a few things to keep your code performant and easy to understand.
|
||||
@@ -49,19 +46,16 @@ Under the hood, React does a few things to keep your code performant and easy to
|
||||
|
||||
**Event delegation:** React doesn't actually attach event handlers to the nodes themselves. When React starts up, it starts listening for all events at the top level using a single event listener. When a component is mounted or unmounted, the event handlers are simply added or removed from an internal mapping. When an event occurs, React knows how to dispatch it using this mapping. When there are no event handlers left in the mapping, React's event handlers are simple no-ops. To learn more about why this is fast, see [David Walsh's excellent blog post](http://davidwalsh.name/event-delegate).
|
||||
|
||||
|
||||
## Components are Just State Machines
|
||||
|
||||
React thinks of UIs as simple state machines. By thinking of a UI as being in various states and rendering those states, it's easy to keep your UI consistent.
|
||||
|
||||
In React, you simply update a component's state, and then render a new UI based on this new state. React takes care of updating the DOM for you in the most efficient way.
|
||||
|
||||
|
||||
## How State Works
|
||||
|
||||
A common way to inform React of a data change is by calling `setState(data, callback)`. This method merges `data` into `this.state` and re-renders the component. When the component finishes re-rendering, the optional `callback` is called. Most of the time you'll never need to provide a `callback` since React will take care of keeping your UI up-to-date for you.
|
||||
|
||||
|
||||
## What Components Should Have State?
|
||||
|
||||
Most of your components should simply take some data from `props` and render it. However, sometimes you need to respond to user input, a server request or the passage of time. For this you use state.
|
||||
@@ -70,15 +64,14 @@ Most of your components should simply take some data from `props` and render it.
|
||||
|
||||
A common pattern is to create several stateless components that just render data, and have a stateful component above them in the hierarchy that passes its state to its children via `props`. The stateful component encapsulates all of the interaction logic, while the stateless components take care of rendering data in a declarative way.
|
||||
|
||||
|
||||
## What *Should* Go in State?
|
||||
|
||||
**State should contain data that a component's event handlers may change to trigger a UI update.** In real apps this data tends to be very small and JSON-serializable. When building a stateful component, think about the minimal possible representation of its state, and only store those properties in `this.state`. Inside of `render()` simply compute any other information you need based on this state. You'll find that thinking about and writing applications in this way tends to lead to the most correct application, since adding redundant or computed values to state means that you need to explicitly keep them in sync rather than rely on React computing them for you.
|
||||
|
||||
## What *Shouldn’t* Go in State?
|
||||
## What *Shouldn't* Go in State?
|
||||
|
||||
`this.state` should only contain the minimal amount of data needed to represent your UI's state. As such, it should not contain:
|
||||
|
||||
* **Computed data:** Don't worry about precomputing values based on state — it's easier to ensure that your UI is consistent if you do all computation within `render()`. For example, if you have an array of list items in state and you want to render the count as a string, simply render `this.state.listItems.length + ' list items'` in your `render()` method rather than storing it on state.
|
||||
* **React components:** Build them in `render()` based on underlying props and state.
|
||||
* **Duplicated data from props:** Try to use props as the source of truth where possible. One valid use to store props in state is to be able to know its previous values, because props can change over time.
|
||||
* **Duplicated data from props:** Try to use props as the source of truth where possible. One valid use to store props in state is to be able to know its previous values, because props may change as the result of a parent component re-rendering.
|
||||
|
||||
@@ -8,12 +8,10 @@ next: reusable-components.html
|
||||
|
||||
So far, we've looked at how to write a single component to display data and handle user input. Next let's examine one of React's finest features: composability.
|
||||
|
||||
|
||||
## Motivation: Separation of Concerns
|
||||
|
||||
By building modular components that reuse other components with well-defined interfaces, you get much of the same benefits that you get by using functions or classes. Specifically you can *separate the different concerns* of your app however you please simply by building new components. By building a custom component library for your application, you are expressing your UI in a way that best fits your domain.
|
||||
|
||||
|
||||
## Composition Example
|
||||
|
||||
Let's create a simple Avatar component which shows a profile picture and username using the Facebook Graph API.
|
||||
@@ -54,14 +52,12 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## Ownership
|
||||
|
||||
In the above example, instances of `Avatar` *own* instances of `ProfilePic` and `ProfileLink`. In React, **an owner is the component that sets the `props` of other components**. More formally, if a component `X` is created in component `Y`'s `render()` method, it is said that `X` is *owned by* `Y`. As discussed earlier, a component cannot mutate its `props` — they are always consistent with what its owner sets them to. This fundamental invariant leads to UIs that are guaranteed to be consistent.
|
||||
|
||||
It's important to draw a distinction between the owner-ownee relationship and the parent-child relationship. The owner-ownee relationship is specific to React, while the parent-child relationship is simply the one you know and love from the DOM. In the example above, `Avatar` owns the `div`, `ProfilePic` and `ProfileLink` instances, and `div` is the **parent** (but not owner) of the `ProfilePic` and `ProfileLink` instances.
|
||||
|
||||
|
||||
## Children
|
||||
|
||||
When you create a React component instance, you can include additional React components or JavaScript expressions between the opening and closing tags like this:
|
||||
@@ -72,7 +68,6 @@ When you create a React component instance, you can include additional React com
|
||||
|
||||
`Parent` can read its children by accessing the special `this.props.children` prop. **`this.props.children` is an opaque data structure:** use the [React.Children utilities](/react/docs/top-level-api.html#react.children) to manipulate them.
|
||||
|
||||
|
||||
### Child Reconciliation
|
||||
|
||||
**Reconciliation is the process by which React updates the DOM with each new render pass.** In general, children are reconciled according to the order in which they are rendered. For example, suppose two render passes generate the following respective markup:
|
||||
@@ -91,7 +86,6 @@ When you create a React component instance, you can include additional React com
|
||||
|
||||
Intuitively, `<p>Paragraph 1</p>` was removed. Instead, React will reconcile the DOM by changing the text content of the first child and destroying the last child. React reconciles according to the *order* of the children.
|
||||
|
||||
|
||||
### Stateful Children
|
||||
|
||||
For most components, this is not a big deal. However, for stateful components that maintain data in `this.state` across render passes, this can be very problematic.
|
||||
@@ -111,7 +105,6 @@ In most cases, this can be sidestepped by hiding elements instead of destroying
|
||||
</Card>
|
||||
```
|
||||
|
||||
|
||||
### Dynamic Children
|
||||
|
||||
The situation gets more complicated when the children are shuffled around (as in search results) or if new components are added onto the front of the list (as in streams). In these cases where the identity and state of each child must be maintained across render passes, you can uniquely identify each child by assigning it a `key`:
|
||||
@@ -178,7 +171,6 @@ You can also key children by passing a ReactFragment object. See [Keyed Fragment
|
||||
|
||||
In React, data flows from owner to owned component through `props` as discussed above. This is effectively one-way data binding: owners bind their owned component's props to some value the owner has computed based on its `props` or `state`. Since this process happens recursively, data changes are automatically reflected everywhere they are used.
|
||||
|
||||
|
||||
## A Note on Performance
|
||||
|
||||
You may be thinking that it's expensive to change data if there are a large number of nodes under an owner. The good news is that JavaScript is fast and `render()` methods tend to be quite simple, so in most applications this is extremely fast. Additionally, the bottleneck is almost always the DOM mutation and not JS execution. React will optimize this for you by using batching and change detection.
|
||||
|
||||
@@ -168,7 +168,7 @@ var MyComponent = React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
也可以传递ReactFragment 对象 来做有 key 的子级。详见[Keyed Fragments](create-fragment.html)
|
||||
也可以传递ReactFragment 对象 来做有 key 的子级。详见[Keyed Fragments](create-fragment.html)
|
||||
|
||||
## 数据流
|
||||
|
||||
@@ -182,5 +182,5 @@ React 里,数据通过上面介绍过的 `props` 从拥有者流向归属者
|
||||
但是,有时候需要做细粒度的性能控制。这种情况下,可以重写 `shouldComponentUpdate()` 方法返回 false 来让 React 跳过对子树的处理。参考 [React reference docs](/react/docs/component-specs.html) 了解更多。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>
|
||||
> 如果在数据变化时让 `shouldComponentUpdate()` 返回 false,React 就不能保证用户界面同步。当使用它的时候一定确保你清楚到底做了什么,并且只在遇到明显性能问题的时候才使用它。不要低估 JavaScript 的速度,DOM 操作通常才是慢的原因。
|
||||
|
||||
@@ -227,4 +227,4 @@ Counter.defaultProps = { initialCount: 0 };
|
||||
|
||||
### ミックスインはありません
|
||||
|
||||
不幸なことに、ES6はミックスインのサポートを行いません。それゆえ、ReactをES6のクラスと一緒に使う際にはミックスインのサポートはありません。代わりに、ミックスインに頼ることなくそれらのユースケースをサポートするのが簡単になるよう努力しています。
|
||||
不幸なことに、ES6はミックスインのサポートを行いません。それゆえ、ReactをES6のクラスと一緒に使う際にはミックスインのサポートはありません。代わりに、ミックスインに頼ることなくそれらのユースケースをサポートするのが簡単になるよう努力しています。
|
||||
|
||||
@@ -8,7 +8,6 @@ next: transferring-props.html
|
||||
|
||||
When designing interfaces, break down the common design elements (buttons, form fields, layout components, etc.) into reusable components with well-defined interfaces. That way, the next time you need to build some UI, you can write much less code. This means faster development time, fewer bugs, and fewer bytes down the wire.
|
||||
|
||||
|
||||
## Prop Validation
|
||||
|
||||
As your app grows it's helpful to ensure that your components are used correctly. We do this by allowing you to specify `propTypes`. `React.PropTypes` exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. Note that for performance reasons `propTypes` is only checked in development mode. Here is an example documenting the different validators provided:
|
||||
@@ -79,7 +78,6 @@ React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Default Prop Values
|
||||
|
||||
React lets you define default values for your `props` in a very declarative way:
|
||||
@@ -97,10 +95,9 @@ var ComponentWithDefaultProps = React.createClass({
|
||||
|
||||
The result of `getDefaultProps()` will be cached and used to ensure that `this.props.value` will have a value if it was not specified by the parent component. This allows you to safely just use your props without having to write repetitive and fragile code to handle that yourself.
|
||||
|
||||
|
||||
## Transferring Props: A Shortcut
|
||||
|
||||
A common type of React component is one that extends a basic HTML element in a simple way. Often you'll want to copy any HTML attributes passed to your component to the underlying HTML element to save typing. You can use the JSX _spread_ syntax to achieve this:
|
||||
A common type of React component is one that extends a basic HTML element in a simple way. Often you'll want to copy any HTML attributes passed to your component to the underlying HTML element. To save typing, you can use the JSX _spread_ syntax to achieve this:
|
||||
|
||||
```javascript
|
||||
var CheckLink = React.createClass({
|
||||
@@ -233,8 +230,6 @@ Methods follow the same semantics as regular ES6 classes, meaning that they don'
|
||||
|
||||
Unfortunately ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes. Instead, we're working on making it easier to support such use cases without resorting to mixins.
|
||||
|
||||
|
||||
|
||||
## Stateless Functions
|
||||
|
||||
You may also define your React classes as a plain JavaScript function. For example using the stateless function syntax:
|
||||
@@ -253,12 +248,10 @@ var HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
|
||||
This simplified component API is intended for components that are pure functions of their props. These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate.
|
||||
|
||||
> NOTE:
|
||||
>
|
||||
>
|
||||
> Because stateless functions don't have a backing instance, you can't attach a ref to a stateless function component. Normally this isn't an issue, since stateless functions do not provide an imperative API. Without an imperative API, there isn't much you could do with an instance anyway. However, if a user wants to find the DOM node of a stateless function component, they must wrap the component in a stateful component (eg. ES6 class component) and attach the ref to the stateful wrapper component.
|
||||
|
||||
In an ideal world, most of your components would be stateless functions because these stateless components can follow a faster code path within the React core. This is the recommended pattern, when possible.
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ ReactDOM.render(
|
||||
## JSX에서 `...`를 사용해 전달하기
|
||||
|
||||
> 주의:
|
||||
>
|
||||
>
|
||||
> 아래의 예제에서는 실험적인 ES7 문법이 사용되었기 때문에 `--harmony ` 플래그가 필요합니다. 브라우저에서 JSX 변환기를 사용 중이라면, `<script type="text/jsx;harmony=true">`를 사용해 스크립트를 작성하세요. 자세히 알아보려면 아래의 [잔여 프로퍼티와 스프레드 프로퍼티 ...](/react/docs/transferring-props-ko-KR.html#rest-and-spread-properties-...)를 확인하세요.
|
||||
|
||||
때로는 모든 프로퍼티를 일일이 전달 하는것은 지루하고 덧없는 작업입니다. 이 경우 [구조 해체 할당(destructuring assignment)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)을 다른 프로퍼티를 함께 사용해 미상의 프로퍼티를 추출할 수 있습니다.
|
||||
|
||||
@@ -83,7 +83,7 @@ ReactDOM.render(
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>
|
||||
> 上面例子中,`checked` 属性也是一个有效的 DOM 属性。如果你没有使用解构赋值,那么可能无意中把它传下去。
|
||||
|
||||
在传递这些未知的 `other` 属性时,要经常使用解构赋值模式。
|
||||
@@ -126,7 +126,7 @@ var FancyCheckbox = React.createClass({
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>
|
||||
> 顺序很重要,把 `{...other}` 放到 JSX props 前面会使它不被覆盖。上面例子中我们可以保证 input 的 type 是 `"checkbox"`。
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ Like all DOM events, the `onChange` prop is supported on all native components a
|
||||
>
|
||||
> For `<input>` and `<textarea>`, `onChange` supersedes — and should generally be used instead of — the DOM's built-in [`oninput`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput) event handler.
|
||||
|
||||
|
||||
## Controlled Components
|
||||
|
||||
An `<input>` with `value` set is a *controlled* component. In a controlled `<input>`, the value of the rendered element will always reflect the `value` prop. For example:
|
||||
@@ -70,8 +69,7 @@ This would accept user input but truncate the value to the first 140 characters.
|
||||
|
||||
### Potential Issues With Checkboxes and Radio Buttons
|
||||
|
||||
Be aware that, in an attempt to normalise change handling for checkbox and radio inputs, React uses a `click` event in place of a `change` event. For the most part this behaves as expected, except when calling `preventDefault` in a `change` handler. `preventDefault` stops the browser from visually updating the input, even if `checked` gets toggled. This can be worked around either by removing the call to `preventDefault`, or putting the toggle of `checked` in a `setTimeout`.
|
||||
|
||||
Be aware that, in an attempt to normalize change handling for checkbox and radio inputs, React uses a `click` event in place of a `change` event. For the most part this behaves as expected, except when calling `preventDefault` in a `change` handler. `preventDefault` stops the browser from visually updating the input, even if `checked` gets toggled. This can be worked around either by removing the call to `preventDefault`, or putting the toggle of `checked` in a `setTimeout`.
|
||||
|
||||
## Uncontrolled Components
|
||||
|
||||
@@ -95,7 +93,7 @@ If you want to initialize the component with a non-empty value, you can supply a
|
||||
}
|
||||
```
|
||||
|
||||
This example will function much like the **Controlled Components** example above.
|
||||
This example will function much like the **Uncontrolled Components** example above.
|
||||
|
||||
Likewise, `<input>` supports `defaultChecked` and `<select>` supports `defaultValue`.
|
||||
|
||||
@@ -103,10 +101,8 @@ Likewise, `<input>` supports `defaultChecked` and `<select>` supports `defaultVa
|
||||
>
|
||||
> The `defaultValue` and `defaultChecked` props are only used during initial render. If you need to update the value in a subsequent render, you will need to use a [controlled component](#controlled-components).
|
||||
|
||||
|
||||
## Advanced Topics
|
||||
|
||||
|
||||
### Why Controlled Components?
|
||||
|
||||
Using form components such as `<input>` in React presents a challenge that is absent when writing traditional form HTML. For example, in HTML:
|
||||
@@ -127,7 +123,6 @@ Unlike HTML, React components must represent the state of the view at any point
|
||||
|
||||
Since this method describes the view at any point in time, the value of the text input should *always* be `Untitled`.
|
||||
|
||||
|
||||
### Why Textarea Value?
|
||||
|
||||
In HTML, the value of `<textarea>` is usually set using its children:
|
||||
@@ -145,7 +140,6 @@ For HTML, this easily allows developers to supply multiline values. However, sin
|
||||
|
||||
If you *do* decide to use children, they will behave like `defaultValue`.
|
||||
|
||||
|
||||
### Why Select Value?
|
||||
|
||||
The selected `<option>` in an HTML `<select>` is normally specified through that option's `selected` attribute. In React, in order to make components easier to manipulate, the following format is adopted instead:
|
||||
|
||||
@@ -7,33 +7,33 @@ next: working-with-the-browser-zh-CN.html
|
||||
---
|
||||
|
||||
诸如 `<input>`、`<textarea>`、`<option>` 这样的表单组件不同于其他组件,因为他们可以通过用户交互发生变化。这些组件提供的界面使响应用户交互的表单数据处理更加容易。
|
||||
|
||||
|
||||
关于 `<form>` 事件详情请查看 [表单事件](/react/docs/events-zh-CN.html#form-events)。
|
||||
|
||||
## 交互属性
|
||||
|
||||
## 交互属性
|
||||
|
||||
表单组件支持几个受用户交互影响的属性:
|
||||
|
||||
|
||||
* `value`,用于 `<input>`、`<textarea>` 组件。
|
||||
* `checked`,用于类型为 `checkbox` 或者 `radio` 的 `<input>` 组件。
|
||||
* `selected`,用于 `<option>` 组件。
|
||||
|
||||
在 HTML 中,`<textarea>` 的值通过子节点设置;在 React 中则应该使用 `value` 代替。
|
||||
在 HTML 中,`<textarea>` 的值通过子节点设置;在 React 中则应该使用 `value` 代替。
|
||||
|
||||
表单组件可以通过 `onChange` 回调函数来监听组件变化。当用户做出以下交互时,`onChange` 执行并通过浏览器做出响应:
|
||||
|
||||
|
||||
* `<input>` 或 `<textarea>` 的 `value` 发生变化时。
|
||||
* `<input>` 的 `checked` 状态改变时。
|
||||
* `<option>` 的 `selected` 状态改变时。
|
||||
|
||||
和所有 DOM 事件一样,所有的 HTML 原生组件都支持 `onChange` 属性,而且可以用来监听冒泡的 `change` 事件。
|
||||
|
||||
|
||||
和所有 DOM 事件一样,所有的 HTML 原生组件都支持 `onChange` 属性,而且可以用来监听冒泡的 `change` 事件。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 对于 `<input>` and `<textarea>`, `onChange` 替代 — 一般应该用来替代 — the DOM's 内建的 [`oninput`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput) 事件处理。
|
||||
|
||||
|
||||
## 受限组件
|
||||
|
||||
## 受限组件
|
||||
|
||||
设置了 `value` 的 `<input>` 是一个*受限*组件。 对于受限的 `<input>`,渲染出来的 HTML 元素始终保持 `value` 属性的值。例如:
|
||||
|
||||
@@ -42,7 +42,7 @@ next: working-with-the-browser-zh-CN.html
|
||||
return <input type="text" value="Hello!" />;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
上面的代码将渲染出一个值为 `Hello!` 的 input 元素。用户在渲染出来的元素里输入任何值都不起作用,因为 React 已经赋值为 `Hello!`。如果想响应更新用户输入的值,就得使用 `onChange` 事件:
|
||||
|
||||
```javascript
|
||||
@@ -72,7 +72,7 @@ next: working-with-the-browser-zh-CN.html
|
||||
|
||||
当心,在力图标准化复选框与单选按钮的变换处理中,React使用`click` 事件代替 `change` 事件。在大多数情况下它们表现的如同预期,除了在`change` handler中调用`preventDefault` 。`preventDefault` 阻止了浏览器视觉上更新输入,即使`checked`被触发。变通的方式是要么移除`preventDefault`的调用,要么把`checked` 的触发放在一个`setTimeout`里。
|
||||
|
||||
|
||||
|
||||
## 不受限组件
|
||||
|
||||
没有设置 `value`(或者设为 `null`) 的 `<input>` 组件是一个*不受限*组件。对于不受限的 `<input>` 组件,渲染出来的元素直接反应用户输入。例如:
|
||||
@@ -102,14 +102,14 @@ next: working-with-the-browser-zh-CN.html
|
||||
> 注意:
|
||||
>
|
||||
> `defaultValue` 和 `defaultChecked` props 只能在内部渲染时被使用。 如果你需要在随后的渲染更新值, 你需要使用 [受限组件](#受限组件).
|
||||
|
||||
|
||||
|
||||
## 高级主题
|
||||
|
||||
|
||||
|
||||
### 为什么使用受限组件?
|
||||
|
||||
在 React 中使用诸如 `<input>` 的表单组件时,遇到了一个在传统 HTML 中没有的挑战。比如下面的代码:
|
||||
在 React 中使用诸如 `<input>` 的表单组件时,遇到了一个在传统 HTML 中没有的挑战。比如下面的代码:
|
||||
|
||||
```html
|
||||
<input type="text" name="title" value="Untitled" />
|
||||
@@ -136,7 +136,7 @@ next: working-with-the-browser-zh-CN.html
|
||||
<!-- 反例:在 React 中不要这样使用! -->
|
||||
<textarea name="description">This is the description.</textarea>
|
||||
```
|
||||
|
||||
|
||||
对 HTML 而言,让开发者设置多行的值很容易。但是,React 是 JavaScript,没有字符限制,可以使用 `\n` 实现换行。简言之,React 已经有 `value`、`defaultValue` 属性,`</textarea>` 组件的子节点扮演什么角色就有点模棱两可了。基于此, 设置 `<textarea>` 值时不应该使用子节点:
|
||||
|
||||
```javascript
|
||||
@@ -146,7 +146,7 @@ next: working-with-the-browser-zh-CN.html
|
||||
如果 *非要* 使用子节点,效果和使用 `defaultValue` 一样。
|
||||
|
||||
|
||||
### 为什么 `<select>` 使用 `value` 属性
|
||||
### 为什么 `<select>` 使用 `value` 属性
|
||||
|
||||
HTML 中 `<select>` 通常使用 `<option>` 的 `selected` 属性设置选中状态;React 为了更方面的控制组件,采用以下方式代替:
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ var MyComponent = React.createClass({
|
||||
ReactDOM.findDOMNode(this.refs.myTextInput).focus();
|
||||
},
|
||||
render: function() {
|
||||
// この参照属性はコンポーネントがマウントされた時に、
|
||||
// この参照属性はコンポーネントがマウントされた時に、
|
||||
// this.refs のコンポーネントへの参照を追加します。
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -137,7 +137,7 @@ _마운트된_ 합성 컴포넌트들은 다음과 같은 메소드를 지원합
|
||||
|
||||
### 크로스 브라우징 이슈
|
||||
|
||||
React가 브라우저별 차이점을 썩 잘 추상화하긴 했지만 일부는 한정적이거나 우리가 발견하지 못한 이상한(quirky) 동작을 보여주기도 합니다.
|
||||
React가 브라우저별 차이점을 썩 잘 추상화하긴 했지만 일부는 한정적이거나 우리가 발견하지 못한 이상한(quirky) 동작을 보여주기도 합니다.
|
||||
|
||||
|
||||
#### IE8에서의 onScroll 이벤트
|
||||
|
||||
@@ -8,21 +8,18 @@ next: more-about-refs.html
|
||||
|
||||
React provides powerful abstractions that free you from touching the DOM directly in most cases, but sometimes you simply need to access the underlying API, perhaps to work with a third-party library or existing code.
|
||||
|
||||
|
||||
## The Virtual DOM
|
||||
|
||||
React is so fast because it never talks to the DOM directly. React maintains a fast in-memory representation of the DOM. `render()` methods return a *description* of the DOM, and React can diff this description with the in-memory representation to compute the fastest way to update the browser.
|
||||
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!
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## Refs and findDOMNode()
|
||||
|
||||
To interact with the browser, you'll need a reference to a DOM node. You can attach a `ref` to any element, which allows you to reference the **backing instance** of the component. This is useful if you need to invoke imperative functions on the component, or want to access the underlying DOM nodes. To learn more about refs, including ways to use them effectively, see our [refs to components](/react/docs/more-about-refs.html) documentation.
|
||||
|
||||
|
||||
## Component Lifecycle
|
||||
|
||||
Components have three main parts of their lifecycle:
|
||||
@@ -33,14 +30,12 @@ Components have three main parts of their lifecycle:
|
||||
|
||||
React provides lifecycle methods that you can specify to hook into this process. We provide **will** methods, which are called right before something happens, and **did** methods which are called right after something happens.
|
||||
|
||||
|
||||
### Mounting
|
||||
|
||||
* `getInitialState(): object` is invoked before a component is mounted. Stateful components should implement this and return the initial state data.
|
||||
* `componentWillMount()` is invoked immediately before mounting occurs.
|
||||
* `componentDidMount()` is invoked immediately after mounting occurs. Initialization that requires DOM nodes should go here.
|
||||
|
||||
|
||||
### Updating
|
||||
|
||||
* `componentWillReceiveProps(object nextProps)` is invoked when a mounted component receives new props. This method should be used to compare `this.props` and `nextProps` to perform state transitions using `this.setState()`.
|
||||
@@ -48,26 +43,22 @@ React provides lifecycle methods that you can specify to hook into this process.
|
||||
* `componentWillUpdate(object nextProps, object nextState)` is invoked immediately before updating occurs. You cannot call `this.setState()` here.
|
||||
* `componentDidUpdate(object prevProps, object prevState)` is invoked immediately after updating occurs.
|
||||
|
||||
|
||||
### Unmounting
|
||||
|
||||
* `componentWillUnmount()` is invoked immediately before a component is unmounted and destroyed. Cleanup should go here.
|
||||
|
||||
|
||||
### Mounted Methods
|
||||
|
||||
_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
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
@@ -94,12 +85,10 @@ The unminified build of React needs the following from [paulmillr's console-poly
|
||||
|
||||
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.
|
||||
|
||||
@@ -9,7 +9,7 @@ next: more-about-refs-zh-CN.html
|
||||
React提供了强大的抽象机制使你在大多数情况下免于直接接触DOM,但有时你仅仅只需要访问底层API,也许是为了与第三方库或者已有的代码协作。
|
||||
|
||||
|
||||
## 虚拟DOM
|
||||
## 虚拟DOM
|
||||
|
||||
React如此快速是因为它从不直接操作DOM。React维持了一个快速的内存中的DOM表示。`render()` 方法返回一个DOM的*描述*,然后React能根据内存中的描述diff此描述来计算出最快速的方法更新浏览器。
|
||||
|
||||
@@ -76,14 +76,14 @@ React提供生命周期方法,以便你可以指定钩挂到这个过程上。
|
||||
### 挂载
|
||||
|
||||
* `getInitialState(): object` 在组件挂载前被调用. 有状态组件(Stateful components) 应该实现此函数并返回初始state的数据。
|
||||
* `componentWillMount()` 在挂载发生前被立即调用。
|
||||
* `componentDidMount()` 在挂载发生后被立即调用。 需要DOM node的初始化应该放在这里。
|
||||
* `componentWillMount()` 在挂载发生前被立即调用。
|
||||
* `componentDidMount()` 在挂载发生后被立即调用。 需要DOM node的初始化应该放在这里。
|
||||
|
||||
|
||||
### 更新
|
||||
|
||||
* `componentWillReceiveProps(object nextProps)` 当挂载的组件接收到新的props时被调用。此方法应该被用于比较`this.props` 和 `nextProps`以用于使用`this.setState()`执行状态转换。
|
||||
* `shouldComponentUpdate(object nextProps, object nextState): boolean` 当组件决定任何改变是否要更新到DOM时被调用。作为一个优化实现比较`this.props` 和 `nextProps` 、`this.state` 和 `nextState` ,如果React应该跳过更新,返回`false`。
|
||||
* `shouldComponentUpdate(object nextProps, object nextState): boolean` 当组件决定任何改变是否要更新到DOM时被调用。作为一个优化实现比较`this.props` 和 `nextProps` 、`this.state` 和 `nextState` ,如果React应该跳过更新,返回`false`。
|
||||
* `componentWillUpdate(object nextProps, object nextState)` 在更新发生前被立即调用。你不能在此调用`this.setState()`。
|
||||
* `componentDidUpdate(object prevProps, object prevState)` 在更新发生后被立即调用。
|
||||
|
||||
@@ -108,7 +108,7 @@ _Mounted_ 复合组件同样支持以下方法:
|
||||
除了这种哲学外,我们也采用了这样的立场,我们,作为一个JS库的作者,不应该把polyfills作为我们库的一部分。如果所有的库这样做,就有很大的机会发送同样的polyfill多次,这可能是一个相当大的无用代码。如果你的产品需要支援老的浏览器,你很有可能已经在使用某些东西比如[es5-shim](https://github.com/es-shims/es5-shim)。
|
||||
|
||||
|
||||
### 需要用来支持旧浏览器的Polyfills
|
||||
### 需要用来支持旧浏览器的Polyfills
|
||||
|
||||
来自 [kriskowal's es5-shim](https://github.com/es-shims/es5-shim)的`es5-shim.js` 提供了如下React需要的东西:
|
||||
|
||||
@@ -135,7 +135,7 @@ _Mounted_ 复合组件同样支持以下方法:
|
||||
当在IE8里使用HTML5元素,包括`<section>`, `<article>`, `<nav>`, `<header>`, 和 `<footer>`, 同样必须包含[html5shiv](https://github.com/aFarkas/html5shiv) 或者类似的脚本。
|
||||
|
||||
|
||||
### 跨浏览器问题
|
||||
### 跨浏览器问题
|
||||
|
||||
尽管React在抽象浏览器不同时做的相当好,但一些浏览器被限制或者表现出怪异的行为,我们没能找到变通的方案解决。
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ next: tooling-integration-zh-CN.html
|
||||
```javascript
|
||||
// 反模式:不能工作.
|
||||
render: function() {
|
||||
var myInput = <input />; // 我打算在这个上调用这个方法
|
||||
var myInput = <input />; // 我打算在这个上调用这个方法
|
||||
this.rememberThisInput = myInput; // input在未来的某个时间点上!YAY!
|
||||
return (
|
||||
<div>
|
||||
@@ -165,10 +165,10 @@ React 假设你可以向任何的从`render()` 中返回的组件附加一个特
|
||||
|
||||
- 执行 DOM操作,总是要求诸如`<input />` 这样的一个“原生”组件,并通过`this.refs.myInput` 来访问她的低层的MOD 节点。Refs是可以做成这个事的唯一的实践可行的方法。
|
||||
|
||||
- Refs自动管理!如果孩子被销毁了,它的ref也被销毁。在这里不用担心内存(除非你做了一些疯狂的事情来自己保持一个引用)。
|
||||
- Refs自动管理!如果孩子被销毁了,它的ref也被销毁。在这里不用担心内存(除非你做了一些疯狂的事情来自己保持一个引用)。
|
||||
|
||||
### 小心:
|
||||
|
||||
- *绝对不要* 在组件的render方法内部- 获 当任何组件的render方法还在调用栈中执行的时候,访问refs 。
|
||||
- *绝对不要* 在组件的render方法内部- 获 当任何组件的render方法还在调用栈中执行的时候,访问refs 。
|
||||
- 如果你想要保护Google 闭包编译器崩溃的内力,确保绝不作为访问一个被特别的设置为一个字符串的属性。这就意味着,如果你用`ref="myRefString"` 来定义你的ref的话,你必须使用`this.refs['myRefsString']` 来访问。
|
||||
- 如果你不是用React做服务器编程的,在你的程序中,你首先的倾向是用refs来“让事情发生“。如果这是正是你的情况的话,花点时间,仔细的想想`state` 在这个组件的结构层次中应在在哪里使用。通常,正确的"拥有" 状态的地方是结构层次的高层。把状态放在那些地方通常可以消除使用`ref` 来”让事情发生” 的渴望 - 相反的,数据流通常能完成你的目标。
|
||||
- 如果你不是用React做服务器编程的,在你的程序中,你首先的倾向是用refs来“让事情发生“。如果这是正是你的情况的话,花点时间,仔细的想想`state` 在这个组件的结构层次中应在在哪里使用。通常,正确的"拥有" 状态的地方是结构层次的高层。把状态放在那些地方通常可以消除使用`ref` 来”让事情发生” 的渴望 - 相反的,数据流通常能完成你的目标。
|
||||
|
||||
@@ -144,4 +144,4 @@ Reactは `render()` からの出力であるコンポーネントであれば何
|
||||
|
||||
- *決して* コンポーネントのレンダリングメソッドの中の参照にアクセスしてはいけません。たとえコンポーネントのレンダリングメソッドのいずれかがコールスタックの中のどこかで動いているとしても。
|
||||
- もしGoogle Closure Compilerのクラッシュからの回復を守りたいなら、文字列として指定されたプロパティとしてアクセスしてはいけないことに気をつけてください。これは、 `ref="myRefString"` として参照が定義されている場合は、 `this.refs['myRefString']` を使ってアクセスしなければいけないことを意味します。
|
||||
- まだReactでプログラムを書いたことがない場合は、アプリケーションで「何かを起こす」ために参照を使おうとするでしょう。もしそのケースだった場合は、時間をかけて `state` がコンポーネントの階層のどこで保持されるべきか批評的に考えてください。多くの場合は、そのstateを「保持する」ための固有の場所が階層の高いレベルにあることがクリアになります。そのstateをその場所に配置することはよく「何かを起こす」ために `ref` を使うための願望を排除します。代わりに、データフローは普通、目標を達成します。
|
||||
- まだReactでプログラムを書いたことがない場合は、アプリケーションで「何かを起こす」ために参照を使おうとするでしょう。もしそのケースだった場合は、時間をかけて `state` がコンポーネントの階層のどこで保持されるべきか批評的に考えてください。多くの場合は、そのstateを「保持する」ための固有の場所が階層の高いレベルにあることがクリアになります。そのstateをその場所に配置することはよく「何かを起こす」ために `ref` を使うための願望を排除します。代わりに、データフローは普通、目標を達成します。
|
||||
|
||||
@@ -33,7 +33,6 @@ myComponentInstance.doSomething();
|
||||
>
|
||||
> This should only ever be used at the top level. Inside components, let your `props` and `state` handle communication with child components, or use one of the other methods of getting a ref (string attribute or callbacks).
|
||||
|
||||
|
||||
## The ref Callback Attribute
|
||||
|
||||
React supports a special attribute that you can attach to any component. The `ref` attribute can be a callback function, and this callback will be executed immediately after the component is mounted. The referenced component will be passed in as a parameter, and the callback function may use the component immediately, or save the reference for future use (or both).
|
||||
@@ -67,7 +66,6 @@ When attaching a ref to a DOM component like `<div />`, you get the DOM node bac
|
||||
|
||||
Note that when the referenced component is unmounted and whenever the ref changes, the old ref will be called with `null` as an argument. This prevents memory leaks in the case that the instance is stored, as in the first example. Also note that when writing refs with inline function expressions as in the examples here, React sees a different function object each time so on every update, ref will be called with `null` immediately before it's called with the component instance.
|
||||
|
||||
|
||||
## The ref String Attribute
|
||||
|
||||
React also supports using a string (instead of a callback) as a ref prop on any component, although this approach is mostly legacy at this point.
|
||||
@@ -86,7 +84,6 @@ React also supports using a string (instead of a callback) as a ref prop on any
|
||||
var inputRect = input.getBoundingClientRect();
|
||||
```
|
||||
|
||||
|
||||
## A Complete Example
|
||||
In order to get a reference to a React component, you can either use `this` to get the current React component, or you can use a ref to get a reference to a component you own. They work like this:
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@ next: tooling-integration-zh-CN.html
|
||||
```
|
||||
|
||||
|
||||
注意,在这个例子中,我们想 "告诉" input 一些东西 - 那些最后它不能从他的props推断出来的东西。在这个场景中我们想 "告诉" 它,它应该转为获得焦点。然而,有一些挑战。从`render()` 返回的东西不是你实际的 "子" 组件的组合,而是一个在某刻特定实例的子组件的 *描述* - 一个快照。
|
||||
注意,在这个例子中,我们想 "告诉" input 一些东西 - 那些最后它不能从他的props推断出来的东西。在这个场景中我们想 "告诉" 它,它应该转为获得焦点。然而,有一些挑战。从`render()` 返回的东西不是你实际的 "子" 组件的组合,而是一个在某刻特定实例的子组件的 *描述* - 一个快照。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 记住,从 `render()`返回的东西不是你的 *实际的* 被渲染出的子组件实例。从 `render()` 返回的东西仅仅是一个在特定时间你的组件的子层级中的子实例的 *描述*。
|
||||
> 记住,从 `render()`返回的东西不是你的 *实际的* 被渲染出的子组件实例。从 `render()` 返回的东西仅仅是一个在特定时间你的组件的子层级中的子实例的 *描述*。
|
||||
|
||||
|
||||
这意味着你万万不要把你从`render()`返回的东西 "抓住不放" 然后期望它变成任何有意义的东西。
|
||||
@@ -61,7 +61,7 @@ next: tooling-integration-zh-CN.html
|
||||
}
|
||||
```
|
||||
|
||||
在这个例子中,`<input />` 仅仅是一个`<input />` 的 *描述*。 这个描述被用于为`<input />`创建一个 *真实的* **支持实例(backing instance)**
|
||||
在这个例子中,`<input />` 仅仅是一个`<input />` 的 *描述*。 这个描述被用于为`<input />`创建一个 *真实的* **支持实例(backing instance)**
|
||||
|
||||
所以我们如何与input的 *真实的*支持实例对话?
|
||||
|
||||
@@ -170,5 +170,5 @@ Refs是一种很好的发送消息给特定子实例(通过流式的Reactive `pr
|
||||
|
||||
- *绝不* 在任何组件的 render 方法中访问 refs - 或者当任何组件的render方法还在调用栈上的任何地方运行时。
|
||||
- 如果你想要保留Google Closure Compiler Crushing resilience,务必不要把指明为字符串的以属性来访问。这意味这你必须用`this.refs['myRefString']`访问,如果你的ref被定义为`ref="myRefString"`。
|
||||
- 如果你没有用React写过数个程序,你的第一反应通常是打算试着用refs来在你的应用里"让事情发生"。如果是这样,花一些时间并且更精密的思考`state`应该属于组件层级的哪个位置。常常,这会变得清晰:正确的"拥有"那个属性的地方应该在层级的更高层上。把state放在那里往往消除了任何使用`ref`来 "让事情发生"的渴望 - 作为替代,数据流通常将完成你的目录。
|
||||
- 如果你没有用React写过数个程序,你的第一反应通常是打算试着用refs来在你的应用里"让事情发生"。如果是这样,花一些时间并且更精密的思考`state`应该属于组件层级的哪个位置。常常,这会变得清晰:正确的"拥有"那个属性的地方应该在层级的更高层上。把state放在那里往往消除了任何使用`ref`来 "让事情发生"的渴望 - 作为替代,数据流通常将完成你的目标。
|
||||
|
||||
|
||||
@@ -38,4 +38,4 @@ JSXを使用したい場合、[ダウンロードページに](/react/downloads.
|
||||
|
||||
### 役に立つオープンソースのプロジェクト
|
||||
|
||||
オープンソースコミュニティがJSXをいくつかのエディタやビルドシステムで使用するためのツールを作成しました。一覧は[JSXのインテグレーション](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations)を参照してください。
|
||||
オープンソースコミュニティがJSXをいくつかのエディタやビルドシステムで使用するためのツールを作成しました。一覧は[JSXのインテグレーション](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations)を参照してください。
|
||||
|
||||
@@ -12,8 +12,7 @@ Every project uses a different system for building and deploying JavaScript. We'
|
||||
|
||||
### CDN-hosted React
|
||||
|
||||
We provide CDN-hosted versions of React [on our download page](/react/downloads.html). These prebuilt files use the UMD module format. Dropping them in with a simple `<script>` tag will inject a `React` global into your environment. It should also work out-of-the-box in CommonJS and AMD environments.
|
||||
|
||||
We provide CDN-hosted versions of React [on our download page](/react/downloads.html). These pre-built files use the UMD module format. Dropping them in with a simple `<script>` tag will inject a `React` global into your environment. It should also work out-of-the-box in CommonJS and AMD environments.
|
||||
|
||||
### Using master
|
||||
|
||||
@@ -29,13 +28,16 @@ If you like using JSX, Babel provides an [in-browser ES6 and JSX transformer for
|
||||
>
|
||||
> The in-browser JSX transformer is fairly large and results in extraneous computation client-side that can be avoided. Do not use it in production — see the next section.
|
||||
|
||||
|
||||
### Productionizing: Precompiled JSX
|
||||
|
||||
If you have [npm](https://www.npmjs.com/), you can run `npm install -g babel`. Babel has built-in support for React v0.12 and v0.13. Tags are automatically transformed to their equivalent `React.createElement(...)`, `displayName` is automatically inferred and added to all React.createClass calls.
|
||||
If you have [npm](https://www.npmjs.com/), you can run `npm install -g babel`. Babel has built-in support for React v0.12+. Tags are automatically transformed to their equivalent `React.createElement(...)`, `displayName` is automatically inferred and added to all React.createClass calls.
|
||||
|
||||
This tool will translate files that use JSX syntax to plain JavaScript files that can run directly in the browser. It will also watch directories for you and automatically transform files when they are changed; for example: `babel --watch src/ --out-dir lib/`.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> If you are using babel 6.x, you will need to install the relevant preset/plugins. To get started, you can run `npm install -g babel babel-preset-react` and then run `babel --presets react --watch src/ --out-dir lib/`. For more information: check out the [babel 6 blog post](http://babeljs.io/blog/2015/10/29/6.0.0/)
|
||||
|
||||
By default JSX files with a `.js` extension are transformed. Run `babel --help` for more information on how to use Babel.
|
||||
|
||||
Example output:
|
||||
@@ -68,7 +70,6 @@ var HelloMessage = React.createClass({
|
||||
ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
|
||||
```
|
||||
|
||||
|
||||
### Helpful Open-Source Projects
|
||||
|
||||
The open-source community has built tools that integrate JSX with several editors and build systems. See [JSX integrations](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations) for the full list.
|
||||
|
||||
@@ -8,17 +8,17 @@ next: animation-zh-CN.html
|
||||
|
||||
`React.addons` 是我们放置一些用来构建React apps的有用的工具的地方。 **这些应该被认为是实验性的** 但是最终批量进入核心代码或者一个有用的工具库中:
|
||||
|
||||
- [`TransitionGroup` 和 `CSSTransitionGroup`](animation.html), 用来处理通常不能简单实现的动画和转换,比如在组件移除之前。
|
||||
- [`LinkedStateMixin`](two-way-binding-helpers.html), 简化用户的表单输入数据与组件状态的协调。
|
||||
- [`cloneWithProps`](clone-with-props.html), 创建React组件的浅拷贝并改变它们的props。
|
||||
- [`TransitionGroup` 和 `CSSTransitionGroup`](animation.html), 用来处理通常不能简单实现的动画和转换,比如在组件移除之前。
|
||||
- [`LinkedStateMixin`](two-way-binding-helpers.html), 简化用户的表单输入数据与组件状态的协调。
|
||||
- [`cloneWithProps`](clone-with-props.html), 创建React组件的浅拷贝并改变它们的props。
|
||||
- [`createFragment`](create-fragment.html), 创建一组外键的子级。
|
||||
- [`update`](update.html), 一个使不可变数据在JavaScript里更易处理的辅助函数。
|
||||
- [`update`](update.html), 一个使不可变数据在JavaScript里更易处理的辅助函数。
|
||||
- [`PureRenderMixin`](pure-render-mixin.html), 一个特定情况下的性能优化器。
|
||||
|
||||
下面的插件只存在开发版(未压缩)React中:
|
||||
|
||||
- [`TestUtils`](test-utils.html), 用于写测试用例的简单的辅助工具(仅存在于未压缩版本)。
|
||||
- [`Perf`](perf.html), 用于测量性能并给你提示哪里可以优化。
|
||||
- [`Perf`](perf.html), 用于测量性能并给你提示哪里可以优化。
|
||||
|
||||
要获取插件,使用 `react-with-addons.js` (和它的压缩副本)而不是通常的 `react.js`。
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ var ImageCarousel = React.createClass({
|
||||
|
||||
### 異なるコンポーネントをレンダリングする
|
||||
|
||||
デフォルトで、 `ReactTransitionGroup` は `span` としてレンダリングされます。この動きは、 `component` プロパティによって変更できます。例えば、 `<ul>` をレンダリングしたい場合は以下のようになります。
|
||||
デフォルトで、 `ReactTransitionGroup` は `span` としてレンダリングされます。この動きは、 `component` プロパティによって変更できます。例えば、 `<ul>` をレンダリングしたい場合は以下のようになります。
|
||||
|
||||
```javascript{1}
|
||||
<ReactTransitionGroup component="ul">
|
||||
|
||||
@@ -6,7 +6,7 @@ prev: addons.html
|
||||
next: two-way-binding-helpers.html
|
||||
---
|
||||
|
||||
React provides a `ReactTransitionGroup` addon component as a low-level API for animation, and a `ReactCSSTransitionGroup` for easily implementing basic CSS animations and transitions.
|
||||
React provides a `ReactTransitionGroup` add-on component as a low-level API for animation, and a `ReactCSSTransitionGroup` for easily implementing basic CSS animations and transitions.
|
||||
|
||||
## High-level API: `ReactCSSTransitionGroup`
|
||||
|
||||
@@ -52,6 +52,7 @@ var TodoList = React.createClass({
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
> Note:
|
||||
>
|
||||
> You must provide [the `key` attribute](/react/docs/multiple-components.html#dynamic-children) for all children of `ReactCSSTransitionGroup`, even when only rendering a single item. This is how React will determine which children have entered, left, or stayed.
|
||||
|
||||
@@ -144,7 +144,7 @@ var TodoList = React.createClass({
|
||||
...
|
||||
```
|
||||
|
||||
### 动画组必须挂载才工作
|
||||
### 动画组必须挂载才工作
|
||||
|
||||
为了使过渡效果应用到子级上,`ReactCSSTransitionGroup`必须已经挂载到了DOM或者 prop `transitionAppear` 必须被设置为 `true`。下面的例子不会工作,因为 `ReactCSSTransitionGroup` 随同新项目被挂载,而不是新项目在它内部被挂载。将这与上面的[入门指南](#入门指南)部分比较一下,看看不同。
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ Reactでは所有者から子要素へと、データの流れは一方向です
|
||||
|
||||
しかし、データやプログラムに戻る流れを読む必要が有るアプリケーションもたくさんあります。例えば、フォームを作る際に、ユーザのインプットを受け取った時には、Reactの `state` を更新したいと思うことはよくあるでしょう。または、JavaScriptでレイアウトを形作ったり、DOM要素のサイズの変化に反応したいと思うでしょう。
|
||||
|
||||
Reactでは、「変更」のイベントを検知し、データソース(普通はDOMです)を読み、コンポーネントのうちの1つの上で `setState()` を呼ぶことでこの要求を満たすことができます。「データフローのループを止めること」は理解しやすく、維持しやすいプログラムを明確に導きます。詳細な情報については、[フォームのドキュメント](/react/docs/forms-ja-JP.html)をご覧ください。
|
||||
Reactでは、「変更」のイベントを検知し、データソース(普通はDOMです)を読み、コンポーネントのうちの1つの上で `setState()` を呼ぶことでこの要求を満たすことができます。「データフローのループを止めること」は理解しやすく、維持しやすいプログラムを明確に導きます。詳細な情報については、[フォームのドキュメント](/react/docs/forms-ja-JP.html)をご覧ください。
|
||||
|
||||
2ウェイバインディングはDOMの値が常にReactの `state` と一致していることを暗黙に強制しますが、簡潔で、多くの種類のアプリケーションをサポートします。上で説明されているような共通のデータフローループパターンのセットアップや、データソースをReactの `state` に「接続する」ための糖衣構文である `ReactLink` が提供されています。
|
||||
|
||||
@@ -111,4 +111,4 @@ var WithoutLink = React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
`valueLink` プロパティも同様にとても単純です。単純に `onChange` イベントをハンドルし、 `this.props.valueLink.requestChange()` を呼び、 `this.props.value` の代わりに `this.props.valueLink.value` を使用します。それだけです!
|
||||
`valueLink` プロパティも同様にとても単純です。単純に `onChange` イベントをハンドルし、 `this.props.valueLink.requestChange()` を呼び、 `this.props.value` の代わりに `this.props.valueLink.value` を使用します。それだけです!
|
||||
|
||||
@@ -45,7 +45,7 @@ var NoLink = React.createClass({
|
||||
|
||||
This works really well and it's very clear how data is flowing, however, with a lot of form fields it could get a bit verbose. Let's use `ReactLink` to save us some typing:
|
||||
|
||||
```javascript{2,7}
|
||||
```javascript{4,9}
|
||||
var LinkedStateMixin = require('react-addons-linked-state-mixin');
|
||||
|
||||
var WithLink = React.createClass({
|
||||
@@ -68,7 +68,6 @@ Note that checkboxes have a special behavior regarding their `value` attribute,
|
||||
<input type="checkbox" checkedLink={this.linkState('booleanValue')} />
|
||||
```
|
||||
|
||||
|
||||
## Under the Hood
|
||||
|
||||
There are two sides to `ReactLink`: the place where you create the `ReactLink` instance and the place where you use it. To prove how simple `ReactLink` is, let's rewrite each side separately to be more explicit.
|
||||
|
||||
@@ -19,14 +19,14 @@ Simulate.{eventName}(
|
||||
|
||||
Simula l'inoltro di un evento su un nodo DOM con dei dati dell'evento opzionali `eventData`. **Questa è probabilmente l'utilità più essenziale in `ReactTestUtils`.**
|
||||
|
||||
**Cliccare un elemento**
|
||||
**Cliccare un elemento**
|
||||
|
||||
```javascript
|
||||
var node = ReactDOM.findDOMNode(this.refs.button);
|
||||
React.addons.TestUtils.Simulate.click(node);
|
||||
```
|
||||
|
||||
**Cambiare il valore di un campo di input e in seguito premere INVIO**
|
||||
**Cambiare il valore di un campo di input e in seguito premere INVIO**
|
||||
|
||||
```javascript
|
||||
var node = ReactDOM.findDOMNode(this.refs.input);
|
||||
|
||||
@@ -23,7 +23,7 @@ Simulate.{eventName}(
|
||||
|
||||
Simulate an event dispatch on a DOM node with optional `eventData` event data. **This is possibly the single most useful utility in `ReactTestUtils`.**
|
||||
|
||||
**Clicking an element**
|
||||
**Clicking an element**
|
||||
|
||||
```javascript
|
||||
// <button ref="button">...</button>
|
||||
@@ -31,7 +31,7 @@ var node = this.refs.button;
|
||||
ReactTestUtils.Simulate.click(node);
|
||||
```
|
||||
|
||||
**Changing the value of an input field and then pressing ENTER**
|
||||
**Changing the value of an input field and then pressing ENTER.**
|
||||
|
||||
```javascript
|
||||
// <input ref="input" />
|
||||
@@ -41,7 +41,7 @@ ReactTestUtils.Simulate.change(node);
|
||||
ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
|
||||
```
|
||||
|
||||
*note that you will have to provide any event property that you're using in your component (e.g. keyCode, which, etc...) as React is not creating any of these for you*
|
||||
*Note that you will have to provide any event property that you're using in your component (e.g. keyCode, which, etc...) as React is not creating any of these for you.*
|
||||
|
||||
`Simulate` has a method for every event that React understands.
|
||||
|
||||
@@ -58,7 +58,7 @@ Render a component into a detached DOM node in the document. **This function req
|
||||
> Note:
|
||||
>
|
||||
> You will need to have `window`, `window.document` and `window.document.createElement`
|
||||
globally available **before** you import React. Otherwise React will think it can't access the DOM and methods like `setState` won't work.
|
||||
globally available **before** you import React. Otherwise React will think it can't access the DOM and methods like `setState` won't work.
|
||||
|
||||
### mockComponent
|
||||
|
||||
@@ -198,7 +198,6 @@ ReactComponent findRenderedComponentWithType(
|
||||
|
||||
Same as `scryRenderedComponentsWithType()` but expects there to be one result and returns that one result, or throws exception if there is any other number of matches besides one.
|
||||
|
||||
|
||||
## Shallow rendering
|
||||
|
||||
Shallow rendering is an experimental feature that lets you render a component "one level deep" and assert facts about what its render method returns, without worrying about the behavior of child components, which are not instantiated or rendered. This does not require a DOM.
|
||||
|
||||
@@ -31,4 +31,4 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
`cloneWithProps` は `key` や `ref` をクローンされた要素に渡すことはありません。 `className` や `style` は自動的にマージされます。
|
||||
`cloneWithProps` は `key` や `ref` をクローンされた要素に渡すことはありません。 `className` や `style` は自動的にマージされます。
|
||||
|
||||
@@ -56,7 +56,7 @@ var newData = React.addons.update(myData, {
|
||||
|
||||
## 使用できるコマンド
|
||||
|
||||
* `{$push: array}` ターゲットに `array` の全ての要素を `push()` します。
|
||||
* `{$push: array}` ターゲットに `array` の全ての要素を `push()` します。
|
||||
* `{$unshift: array}` ターゲットの `array` の全ての要素を `unshift()` します。
|
||||
* `{$splice: array of arrays}` `arrays` の全ての要素について、その要素によって提供されるパラメータのターゲットにおいて、 `splice()` を呼び出します。
|
||||
* `{$set: any}` ターゲットを完全に置き換えます。
|
||||
|
||||
@@ -20,7 +20,7 @@ myData.x.y.z = 7;
|
||||
myData.a.b.push(9);
|
||||
```
|
||||
|
||||
you have no way of determining which data has changed since the previous copy has been overwritten. Instead, you need to create a new copy of `myData` and change only the parts of it that need to be changed. Then you can compare the old copy of `myData` with the new one in `shouldComponentUpdate()` using triple-equals:
|
||||
You have no way of determining which data has changed since the previous copy has been overwritten. Instead, you need to create a new copy of `myData` and change only the parts of it that need to be changed. Then you can compare the old copy of `myData` with the new one in `shouldComponentUpdate()` using triple-equals:
|
||||
|
||||
```js
|
||||
var newData = deepCopy(myData);
|
||||
|
||||
@@ -25,4 +25,4 @@ React.createClass({
|
||||
|
||||
> 注意:
|
||||
> このミックスインはオブジェクトの比較のみを行います。それらが複雑なデータ構造を持っていた場合、深い位置における違いは見逃されることがあります。単純なpropsやstateをコンポーネントが持っている場合にのみ、使用してください。深いデータ構造が変更されることが分かっている場合は、 `forceUpdate()` を使用してください。または、ネストされたデータの比較を速く行うために[不変オブジェクト](https://facebook.github.io/immutable-js/)の使用を考えてみてください。
|
||||
> 更に、 `shouldComponentUpdate` は全てのコンポーネントのサブツリーのアップデートをスキップします。全ての子要素のコンポーネントもまた、「ピュア」であることを確認してください。
|
||||
> 更に、 `shouldComponentUpdate` は全てのコンポーネントのサブツリーのアップデートをスキップします。全ての子要素のコンポーネントもまた、「ピュア」であることを確認してください。
|
||||
|
||||
@@ -11,7 +11,7 @@ If your React component's render function is "pure" (in other words, it renders
|
||||
Example:
|
||||
|
||||
```js
|
||||
var PureRenderMixin = require('react/addons').addons.PureRenderMixin;
|
||||
var PureRenderMixin = require('react-addons-pure-render-mixin');
|
||||
React.createClass({
|
||||
mixins: [PureRenderMixin],
|
||||
|
||||
|
||||
@@ -202,4 +202,4 @@ this.messages = this.messages.push(new Message({
|
||||
|
||||
データ構造が不変であることで、push関数の結果を `this.messages` にアサインする必要があることに注意してください。
|
||||
|
||||
Reactの側では、 immutable-js のデータ構造をコンポーネントの state を保持するために使用する場合は、 `PureRenderMixin` をコンポーネントにミックスし、再レンダリングのプロセスを短縮することもできます。
|
||||
Reactの側では、 immutable-js のデータ構造をコンポーネントの state を保持するために使用する場合は、 `PureRenderMixin` をコンポーネントにミックスし、再レンダリングのプロセスを短縮することもできます。
|
||||
|
||||
@@ -3,6 +3,7 @@ id: advanced-performance
|
||||
title: Advanced Performance
|
||||
permalink: advanced-performance.html
|
||||
prev: perf.html
|
||||
next: context.html
|
||||
---
|
||||
|
||||
One of the first questions people ask when considering React for a project is whether their application will be as fast and responsive as an equivalent non-React version. The idea of re-rendering an entire subtree of components in response to every state change makes people wonder whether this process negatively impacts performance. React uses several clever techniques to minimize the number of costly DOM operations required to update the UI.
|
||||
|
||||
136
docs/docs/12-context.md
Normal file
136
docs/docs/12-context.md
Normal file
@@ -0,0 +1,136 @@
|
||||
---
|
||||
id: context
|
||||
title: Context
|
||||
permalink: context.html
|
||||
prev: advanced-performance.html
|
||||
---
|
||||
|
||||
One of React's biggest strengths is that it's easy to track the flow of data through your React components. When you look at a component, you can easily see exactly which props are being passed in which makes your apps easy to reason about.
|
||||
|
||||
Occasionally, you want to pass data through the component tree without having to pass the props down manually at every level. React's "context" feature lets you do this.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> Context is an advanced and experimental feature. The API is likely to change in future releases.
|
||||
>
|
||||
> Most applications will never need to use context. Especially if you are just getting started with React, you likely do not want to use context. Using context will make your code harder to understand because it makes the data flow less clear. It is similar to using global variables to pass state through your application.
|
||||
>
|
||||
> **If you have to use context, use it sparingly.**
|
||||
>
|
||||
> Regardless of whether you're building an application or a library, try to isolate your use of context to a small area and avoid using the context API directly when possible so that it's easier to upgrade when the API changes.
|
||||
|
||||
## Passing info automatically through a tree
|
||||
|
||||
Suppose you have a structure like:
|
||||
|
||||
```javascript
|
||||
var Button = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<button style={{'{{'}}background: this.props.color}}>
|
||||
{this.props.children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Message = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.text} <Button color={this.props.color}>Delete</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var MessageList = React.createClass({
|
||||
render: function() {
|
||||
var color = "purple";
|
||||
var children = this.props.messages.map(function(message) {
|
||||
return <Message text={message.text} color={color} />;
|
||||
});
|
||||
return <div>{children}</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
In this example, we manually thread through a `color` prop in order to style the `Button` and `Message` components appropriately. Theming is a good example of when you might want an entire subtree to have access to some piece of information (a color). Using context, we can pass this through the tree automatically:
|
||||
|
||||
```javascript{2-4,7,18,25-30,33}
|
||||
var Button = React.createClass({
|
||||
contextTypes: {
|
||||
color: React.PropTypes.string
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<button style={{'{{'}}background: this.context.color}}>
|
||||
{this.props.children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Message = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.text} <Button>Delete</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var MessageList = React.createClass({
|
||||
childContextTypes: {
|
||||
color: React.PropTypes.string
|
||||
},
|
||||
getChildContext: function() {
|
||||
return {color: "purple"};
|
||||
},
|
||||
render: function() {
|
||||
var children = this.props.messages.map(function(message) {
|
||||
return <Message text={message.text} />;
|
||||
});
|
||||
return <div>{children}</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
By adding `childContextTypes` and `getChildContext` to `MessageList` (the context provider), React passes the information down automatically and any component in the subtree (in this case, `Button`) can access it by defining `contextTypes`.
|
||||
|
||||
If `contextTypes` is not defined, then `this.context` will be an empty object.
|
||||
|
||||
## Parent-child coupling
|
||||
|
||||
Context can also let you build an API such as:
|
||||
|
||||
```javascript
|
||||
<Menu>
|
||||
<MenuItem>aubergine</MenuItem>
|
||||
<MenuItem>butternut squash</MenuItem>
|
||||
<MenuItem>clementine</MenuItem>
|
||||
</Menu>
|
||||
```
|
||||
|
||||
By passing down the relevant info in the `Menu` component, each `MenuItem` can communicate back to the containing `Menu` component.
|
||||
|
||||
**Before you build components with this API, consider if there are cleaner alternatives.** We're fond of simply passing the items as an array in cases like this:
|
||||
|
||||
```javascript
|
||||
<Menu items={['aubergine', 'butternut squash', 'clementine']} />
|
||||
```
|
||||
|
||||
Recall that you can also pass entire React components in props if you'd like to.
|
||||
|
||||
## When not to use context
|
||||
|
||||
Just as global variables are best avoided when writing clear code, you should avoid using context in most cases. In particular, think twice before using it to "save typing" and using it instead of passing explicit props.
|
||||
|
||||
The best use cases for context are for implicitly passing down the logged-in user, the current language, or theme information. All of these might otherwise be true globals, but context lets you scope them to a single React subtree.
|
||||
|
||||
Do not use context to pass your model data through components. Threading your data through the tree explicitly is much easier to understand. Using context makes your components more coupled and less reusable, because they behave differently depending on where they're rendered.
|
||||
|
||||
## Known limitations
|
||||
|
||||
If a context value provided by a component changes, descendants that use that value won't update if an intermediate parent returns `false` from `shouldComponentUpdate`. See issue [#2517](https://github.com/facebook/react/issues/2517) for more details.
|
||||
@@ -13,13 +13,37 @@ React를 시작하는 가장 빠른 방법은 다음의 Hello World JSFiddle 예
|
||||
* **[React JSFiddle](https://jsfiddle.net/reactjs/69z2wepo/)**
|
||||
* [React JSFiddle without JSX](https://jsfiddle.net/reactjs/5vjqabv3/)
|
||||
|
||||
## 초심자용 키트
|
||||
## npm으로 React 사용하기
|
||||
|
||||
초심자용 키트를 내려받아 시작합니다.
|
||||
React는 CommonJS 모듈과 유사한 시스템인 [browserify](http://browserify.org/) 또는 [webpack](https://webpack.github.io/)를 사용하기를 추천합니다.
|
||||
[`react`](https://www.npmjs.com/package/react) 와 [`react-dom`](https://www.npmjs.com/package/react-dom) npm
|
||||
패키지를 이용합니다.
|
||||
|
||||
```js
|
||||
// main.js
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
|
||||
ReactDOM.render(
|
||||
<h1>Hello, world!</h1>,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
browserify를 설치한 후에 React DOM을 설치하고 bundle을 빌드합니다.
|
||||
|
||||
```sh
|
||||
$ npm install --save react react-dom
|
||||
$ browserify -t babelify main.js -o bundle.js
|
||||
```
|
||||
|
||||
## npm 없이 Quick Start 하기
|
||||
|
||||
만약 당신이 npm을 사용할 준비가 아직 안되었다면, 미리빌드된 React와 React DOM 파일이 포함된 초심자용 키트를 다운로드 받을 수 있습니다.
|
||||
|
||||
<div class="buttons-unit downloads">
|
||||
<a href="/react/downloads/react-{{site.react_version}}.zip" class="button">
|
||||
초심자용 키트 내려받기 {{site.react_version}}
|
||||
Download Starter Kit {{site.react_version}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -32,6 +56,7 @@ React를 시작하는 가장 빠른 방법은 다음의 Hello World JSFiddle 예
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React!</title>
|
||||
<script src="build/react.js"></script>
|
||||
<script src="build/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
@@ -46,7 +71,7 @@ React를 시작하는 가장 빠른 방법은 다음의 Hello World JSFiddle 예
|
||||
</html>
|
||||
```
|
||||
|
||||
JavaScript 안에 보이는 XML 구문은 JSX라고 합니다; 더 자세한 내용은 [JSX syntax](/react/docs/jsx-in-depth-ko-KR.html)을 확인하세요. 일반적인 JavaScript로 번역하기 위해 `<script type="text/jsx">`를 사용하고 `JSXTransformer.js`를 포함하는 것으로 실제로 브라우저에서 변환작업을 수행합니다.
|
||||
JavaScript 안에 보이는 XML 구문은 JSX라고 합니다; 더 자세한 내용은 [JSX syntax](/react/docs/jsx-in-depth-ko-KR.html)을 확인하세요. vanilla JavaScript로 번역하기 위해 `<script type="text/babel">`를 사용하고 Babel을 포함하는 것으로 실제로 브라우저에서 변환작업을 수행합니다.
|
||||
|
||||
### 파일의 분리
|
||||
|
||||
@@ -69,19 +94,20 @@ ReactDOM.render(
|
||||
|
||||
### 오프라인 변환
|
||||
|
||||
먼저 커맨드라인 도구를 설치합니다. ([npm](https://www.npmjs.com/) 필요):
|
||||
먼저 [Babel](http://babeljs.io/) 커맨드라인 도구를 설치합니다. ([npm](https://www.npmjs.com/) 필요):
|
||||
|
||||
```
|
||||
npm install -g react-tools
|
||||
npm install --global babel
|
||||
```
|
||||
|
||||
그다음, `src/helloworld.js` 파일을 일반 JavaScript 파일로 변환합니다:
|
||||
|
||||
```
|
||||
jsx --watch src/ build/
|
||||
babel src --watch --out-dir build
|
||||
|
||||
```
|
||||
|
||||
수정할 때마다 `build/helloworld.js` 파일이 자동생성됩니다.
|
||||
수정할 때마다 `build/helloworld.js` 파일이 자동생성됩니다. 더 깊이 사용하고 싶으면 [Babel CLI documentation](http://babeljs.io/docs/usage/cli/)를 읽어보세요.
|
||||
|
||||
```javascript{2}
|
||||
ReactDOM.render(
|
||||
@@ -92,14 +118,15 @@ ReactDOM.render(
|
||||
|
||||
아래의 내용대로 HTML 파일을 업데이트합니다:
|
||||
|
||||
```html{7,11}
|
||||
```html{8,12}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React!</title>
|
||||
<script src="build/react.js"></script>
|
||||
<!-- Babel는 이제 불필요합니다! -->
|
||||
<script src="build/react-dom.js"></script>
|
||||
<!-- No need for Babel! -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
@@ -108,10 +135,6 @@ ReactDOM.render(
|
||||
</html>
|
||||
```
|
||||
|
||||
## CommonJS를 원하시나요?
|
||||
|
||||
만약 React를 [browserify](http://browserify.org/), [webpack](https://webpack.github.io/)이나 기타 CommonJS와 호환되는 모듈시스템과 함께 사용하고 싶다면, [`react` npm 패키지](https://www.npmjs.com/package/react)를 사용하세요. 그 외에도 `jsx` 빌드툴은 아주 쉽게 CommonJS 외에도 대부분의 패키징 시스템에 통합될 수 있습니다.
|
||||
|
||||
## 다음 단계로
|
||||
|
||||
더 알아보려면 [튜토리얼](/react/docs/tutorial-ko-KR.html)과 초심자용 키트의 `examples` 디렉터리에서 다른 예제들을 확인해 보세요.
|
||||
|
||||
@@ -13,9 +13,35 @@ redirect_from: "docs/index-zh-CN.html"
|
||||
* **[React JSFiddle](https://jsfiddle.net/reactjs/69z2wepo/)**
|
||||
* [React JSFiddle without JSX](https://jsfiddle.net/reactjs/5vjqabv3/)
|
||||
|
||||
## 入门教程包 (Starter Kit)
|
||||
|
||||
开始先下载入门教程包。
|
||||
## 通过 npm 使用 React
|
||||
|
||||
我们建议在 React 中使用 CommonJS 模块系统,比如 [browserify](http://browserify.org/) 或 [webpack](https://webpack.github.io/)。使用 [`react`](https://www.npmjs.com/package/react) 和 [`react-dom`](https://www.npmjs.com/package/react-dom) npm 包.
|
||||
|
||||
```js
|
||||
// main.js
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
|
||||
ReactDOM.render(
|
||||
<h1>Hello, world!</h1>,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
在安装 browserify 之后安装 React DOM 和构建你的应用包。
|
||||
|
||||
```sh
|
||||
$ npm install --save react react-dom
|
||||
$ browserify -t babelify main.js -o bundle.js
|
||||
```
|
||||
|
||||
## 不使用 npm 快速开始
|
||||
|
||||
|
||||
If you're not ready to use npm yet, you can download the starter kit which includes prebuilt copies of React and React DOM.
|
||||
如果你没有做好使用 npm 的准备,你可以下载包含了 React 和 ReactDOM 预生成包的入门教程包。
|
||||
|
||||
<div class="buttons-unit downloads">
|
||||
<a href="/react/downloads/react-{{site.react_version}}.zip" class="button">
|
||||
@@ -23,7 +49,7 @@ redirect_from: "docs/index-zh-CN.html"
|
||||
</a>
|
||||
</div>
|
||||
|
||||
在入门教程包的根目录,创建一个含有下面代码的 `helloworld.html`。
|
||||
在入门教程包的根目录,创建一个含有如下代码的 `helloworld.html`。
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
@@ -32,6 +58,7 @@ redirect_from: "docs/index-zh-CN.html"
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React!</title>
|
||||
<script src="build/react.js"></script>
|
||||
<script src="build/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
@@ -46,7 +73,7 @@ redirect_from: "docs/index-zh-CN.html"
|
||||
</html>
|
||||
```
|
||||
|
||||
在 JavaScript 代码里写着 XML 格式的代码称为 JSX;可以去 [JSX 语法](/react/docs/jsx-in-depth.html) 里学习更多 JSX 相关的知识。为了把 JSX 转成标准的 JavaScript,我们用 `<script type="text/jsx">` 标签包裹着含有 JSX 的代码,然后引入 `JSXTransformer.js` 库来实现在浏览器里的代码转换。
|
||||
在 JavaScript 代码里写着 XML 格式的代码称为 JSX;可以去 [JSX 语法](/react/docs/jsx-in-depth.html) 里学习更多 JSX 相关的知识。为了把 JSX 转成标准的 JavaScript,我们用 `<script type="text/babel">` 标签,并引入 Babel 来完成在浏览器里的代码转换。
|
||||
|
||||
### 分离文件
|
||||
|
||||
@@ -65,22 +92,25 @@ ReactDOM.render(
|
||||
<script type="text/babel" src="src/helloworld.js"></script>
|
||||
```
|
||||
|
||||
注意一些浏览器(比如 Chrome )会在使用 HTTP 以外的协议加载文件时失败。
|
||||
|
||||
### 离线转换
|
||||
|
||||
先安装命令行工具(依赖 [npm](https://www.npmjs.com/)):
|
||||
先安装[Babel](http://babeljs.io/)命令行工具(依赖 [npm](https://www.npmjs.com/)):
|
||||
|
||||
```
|
||||
npm install -g react-tools
|
||||
npm install --global babel
|
||||
```
|
||||
|
||||
然后把你的 `src/helloworld.js` 文件转成标准的 JavaScript:
|
||||
|
||||
```
|
||||
jsx --watch src/ build/
|
||||
babel src --watch --out-dir build
|
||||
|
||||
```
|
||||
|
||||
只要你修改了, `build/helloworld.js` 文件会自动生成。
|
||||
`build/helloworld.js` 会在你对文件进行修改时自动生成。 阅读 [Babel CLI 文档](http://babeljs.io/docs/usage/cli/) 了解高级用法。
|
||||
|
||||
|
||||
```javascript{2}
|
||||
ReactDOM.render(
|
||||
@@ -108,10 +138,6 @@ ReactDOM.render(
|
||||
```
|
||||
|
||||
|
||||
## 想用 CommonJS?
|
||||
|
||||
如果你想在 [browserify](http://browserify.org/),[webpack](https://webpack.github.io/) 或者或其它兼容CommonJS的模块系统里使用 React,只要使用 [`react` npm 包](https://www.npmjs.com/package/react) 即可。而且,`jsx` 转换工具可以很轻松的地集成到大部分打包系统里(不仅仅是 CommonJS)。
|
||||
|
||||
|
||||
## 下一步
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ ReactComponent render(
|
||||
|
||||
> 注意:
|
||||
> `React.render()` は渡されたコンテナーノードの内容を制御します。内部に存在するDOM要素は最初に呼ばれた際に置き換えられます。その後に呼ばれた場合は、ReactのDOMの差分アルゴリズムを使用して、効率的に更新されます。
|
||||
>
|
||||
>
|
||||
> `React.render()` はコンテナーノードの変更は行いません(コンテナの子要素のみ変更を行います)。今後、存在する子要素を上書きすることなく、存在するDOMノードにコンポーネントを挿入することが可能になるでしょう。
|
||||
|
||||
### React.unmountComponentAtNode
|
||||
|
||||
@@ -97,10 +97,10 @@ Verifies the object is a ReactElement.
|
||||
#### React.Children.map
|
||||
|
||||
```javascript
|
||||
object React.Children.map(object children, function fn [, object thisArg])
|
||||
array React.Children.map(object children, function fn [, object thisArg])
|
||||
```
|
||||
|
||||
Invoke `fn` on every immediate child contained within `children` with `this` set to `thisArg`. If `children` is a nested object or array it will be traversed: `fn` will never be passed the container objects. If children is `null` or `undefined` returns `null` or `undefined` rather than an empty object.
|
||||
Invoke `fn` on every immediate child contained within `children` with `this` set to `thisArg`. If `children` is a nested object or array it will be traversed: `fn` will never be passed the container objects. If children is `null` or `undefined` returns `null` or `undefined` rather than an array.
|
||||
|
||||
#### React.Children.forEach
|
||||
|
||||
@@ -108,7 +108,7 @@ Invoke `fn` on every immediate child contained within `children` with `this` set
|
||||
React.Children.forEach(object children, function fn [, object thisArg])
|
||||
```
|
||||
|
||||
Like `React.Children.map()` but does not return an object.
|
||||
Like `React.Children.map()` but does not return an array.
|
||||
|
||||
#### React.Children.count
|
||||
|
||||
@@ -126,6 +126,14 @@ object React.Children.only(object children)
|
||||
|
||||
Return the only child in `children`. Throws otherwise.
|
||||
|
||||
#### React.Children.toArray
|
||||
|
||||
```javascript
|
||||
array React.Children.toArray(object children)
|
||||
```
|
||||
|
||||
Return the `children` opaque data structure as a flat array with keys assigned to each child. Useful if you want to manipulate collections of children in your render methods, especially if you want to reorder or slice `this.props.children` before passing it down.
|
||||
|
||||
## ReactDOM
|
||||
|
||||
The `react-dom` package provides DOM-specific methods that can be used at the top level of your app and as an escape hatch to get outside of the React model if you need to. Most of your components should not need to use this module.
|
||||
|
||||
191
docs/docs/ref-01-top-level-api.zh-CN.md
Normal file
191
docs/docs/ref-01-top-level-api.zh-CN.md
Normal file
@@ -0,0 +1,191 @@
|
||||
---
|
||||
id: top-level-api-zh-CN
|
||||
title: Top-Level API
|
||||
permalink: top-level-api-zh-CN.html
|
||||
next: component-api-zh-CN.html
|
||||
redirect_from: "/docs/reference-zh-CN.html"
|
||||
---
|
||||
|
||||
## React
|
||||
|
||||
`React` 是 React 库的入口点。如果你使用预编译包中的一个,则 `React` 为全局变量;如果你使用 CommonJS 模块,你可以 `require()` 它。
|
||||
|
||||
|
||||
### React.Component
|
||||
|
||||
```javascript
|
||||
class Component
|
||||
```
|
||||
|
||||
当使用ES6 类定义时,React.Component是 React 组件的基类。如何在React中使用 ES6 class 请参见 [可重用组件](/react/docs/reusable-components-zh-CN.html#es6-classes)。基类实际提供了哪些方法 请参见 [组件 API](/react/docs/component-api-zh-CN.html).
|
||||
|
||||
|
||||
### React.createClass
|
||||
|
||||
```javascript
|
||||
ReactClass createClass(object specification)
|
||||
```
|
||||
|
||||
给定一份规格(specification),创建一个组件类。组件通常要实现一个 `render()` 方法,它返回 **单个的** 子级。该子级可能包含任意深度的子级结构。组件与标准原型类的不同之处在于,你不需要对它们调用 new。 它们是为你在后台构造实例(通过 new)的便利的包装器。
|
||||
|
||||
更多关于规格对象(specification object)的信息,请见 [组件规格和生命周期](/react/docs/component-specs-zh-CN.html) 。
|
||||
|
||||
|
||||
### React.createElement
|
||||
|
||||
```javascript
|
||||
ReactElement createElement(
|
||||
string/ReactClass type,
|
||||
[object props],
|
||||
[children ...]
|
||||
)
|
||||
```
|
||||
|
||||
创建并返回一个新的给定类型的 `ReactElement`。type 参数既可以是一个 html 标签名字符串(例如. “div”,“span”,等等),也可以是一个 `ReactClass` (用 `React.createClass` 创建的)。
|
||||
|
||||
|
||||
|
||||
### React.cloneElement
|
||||
|
||||
```
|
||||
ReactElement cloneElement(
|
||||
ReactElement element,
|
||||
[object props],
|
||||
[children ...]
|
||||
)
|
||||
```
|
||||
|
||||
使用 `element` 作为起点,克隆并返回一个新的 `ReactElement` 。生成的 element 将会拥有原始 element 的 props 与新的 props 的浅合并。新的子级将会替换现存的子级。 不同于 `React.addons.cloneWithProps`,来自原始 element 的 `key` 和 `ref` 将会保留。对于合并任何 props 没有特别的行为(不同于 `cloneWithProps`)。更多细节详见[v0.13 RC2 blog post](/react/blog/2015/03/03/react-v0.13-rc2.html) 。
|
||||
|
||||
|
||||
### React.createFactory
|
||||
|
||||
```javascript
|
||||
factoryFunction createFactory(
|
||||
string/ReactClass type
|
||||
)
|
||||
```
|
||||
|
||||
返回一个生成给定类型的 ReactElements 的函数。如同 `React.createElement`,type 参数既可以是一个 html 标签名字符串(例如. “div”,“span”,等等),也可以是一个 `ReactClass` 。
|
||||
|
||||
|
||||
|
||||
|
||||
### React.render
|
||||
|
||||
```javascript
|
||||
ReactComponent render(
|
||||
ReactElement element,
|
||||
DOMElement container,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
渲染一个 ReactElement 到 DOM 里提供的 `容器(container)`中,并返回一个对组件的引用。
|
||||
|
||||
如果 ReactElement 之前被渲染到了 `container` 中,这将对它执行一次更新,并仅变动需要变动的 DOM 来反映最新的 React 组件。
|
||||
|
||||
如果提供了可选的回调函数,则该函数将会在组件渲染或者更新之后被执行。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> `React.render()` 控制你传入的 container 节点的内容。
|
||||
> 当初次调用时,任何现存于内的 DOM 元素将被替换。
|
||||
> 其后的调用使用 React的 diffing 算法来有效率的更新。
|
||||
>
|
||||
> `React.render()` 不会修改 container 节点(只修改 container 的子级)。
|
||||
> 将来,也许能够直接插入一个组件到已经存在的 DOM 节点而不覆盖
|
||||
> 现有的子级。
|
||||
|
||||
|
||||
### React.unmountComponentAtNode
|
||||
|
||||
```javascript
|
||||
boolean unmountComponentAtNode(DOMElement container)
|
||||
```
|
||||
|
||||
从 DOM 中移除已经挂载的 React 组件,并清除它的事件处理器和 state。如果在 container 中没有组件被挂载,调用此函数将什么都不做。如果组件被卸载返回 `true`,如果没有组件被卸载返回 `false`。
|
||||
|
||||
|
||||
### React.renderToString
|
||||
|
||||
```javascript
|
||||
string renderToString(ReactElement element)
|
||||
```
|
||||
|
||||
把 ReactElement 渲染为它原始的 HTML 。这应该仅在服务器端使用。React 将会返回一个 HTML 字符串。你可以用这种方法在服务器端生成 HTML,然后在初始请求下传这些标记,以获得更快的页面加载速度及允许搜索引擎抓取页面(便于 SEO)。
|
||||
|
||||
如果在一个在已经有了这种服务器预渲染标记的节点上面调用 `React.render()`,React 将会维护该节点,仅绑定事件处理器,让你有一个非常高效的初次加载体验。
|
||||
|
||||
|
||||
### React.renderToStaticMarkup
|
||||
|
||||
```javascript
|
||||
string renderToStaticMarkup(ReactElement element)
|
||||
```
|
||||
|
||||
类似于 `renderToString` ,除了不创建额外的 DOM 属性,比如 `data-react-id`,这仅在 React 内部使用的属性。如果你想用 React 做一个简单的静态页面生成器,这是很有用的,因为去除额外的属性能够节省很多字节。
|
||||
|
||||
|
||||
### React.isValidElement
|
||||
|
||||
```javascript
|
||||
boolean isValidElement(* object)
|
||||
```
|
||||
|
||||
验证对象是否是一个 ReactElement。
|
||||
|
||||
|
||||
### React.findDOMNode
|
||||
|
||||
```javascript
|
||||
DOMElement findDOMNode(ReactComponent component)
|
||||
```
|
||||
如果这个组件已经被挂载到了 DOM,它返回相应的浏览器原生的 DOM 元素。这个方法对于读取 DOM 的值很有用,比如表单域的值和执行 DOM 的测量。如果 `render` 返回 `null` 或者 `false`, `findDOMNode` 返回 `null`.
|
||||
|
||||
|
||||
### React.DOM
|
||||
|
||||
`React.DOM` 用 `React.createElement` 为 DOM 组件提供了便利的包装器。该方式应该只在不使用 JSX 的时使用。例如,`React.DOM.div(null, 'Hello World!')`。
|
||||
|
||||
|
||||
### React.PropTypes
|
||||
|
||||
`React.PropTypes` 包含了能与 组件的`propTypes` 对象一起使用的类型,用以验证传入你的组件的 props。更多有关 `propTypes` 的信息,请见 [可重用组件](/react/docs/reusable-components-zh-CN.html)。
|
||||
|
||||
|
||||
### React.Children
|
||||
|
||||
`React.Children` 为处理 `this.props.children` 这个不透明的数据结构提供了工具。
|
||||
|
||||
#### React.Children.map
|
||||
|
||||
```javascript
|
||||
object React.Children.map(object children, function fn [, object thisArg])
|
||||
```
|
||||
|
||||
在每一个包含在 `children` 中的直接子级上调用 `fn` ,`fn`中的 `this` 设置为 `thisArg`。如果 `children` 是一个嵌套的对象或者数组,它将被遍历:不会传入容器对象到 `fn` 中。如果 children 是 `null` 或者 `undefined`,则返回 `null` 或者 `undefined` 而不是一个空对象。
|
||||
|
||||
#### React.Children.forEach
|
||||
|
||||
```javascript
|
||||
React.Children.forEach(object children, function fn [, object thisArg])
|
||||
```
|
||||
|
||||
类似 `React.Children.map()`,但是不返回对象。
|
||||
|
||||
#### React.Children.count
|
||||
|
||||
```javascript
|
||||
number React.Children.count(object children)
|
||||
```
|
||||
|
||||
返回 `children` 中的组件总数,相等于传递给 `map` 或者 `forEach` 的回调函数应被调用次数。
|
||||
|
||||
#### React.Children.only
|
||||
|
||||
```javascript
|
||||
object React.Children.only(object children)
|
||||
```
|
||||
|
||||
返回 `children` 中仅有的子级。否则抛出异常。
|
||||
@@ -29,7 +29,7 @@ Here is the simple object usage:
|
||||
setState({mykey: 'my new value'});
|
||||
```
|
||||
|
||||
It's also possible to pass a function with the signature `function(state, props)`. This can be useful in some cases when you want to enqueue an atomic update that consults the previous value of state+props before setting any values. For instance, suppose we wanted to increment a value in state:
|
||||
It's also possible to pass a function with the signature `function(state, props)`. This can be useful in some cases when you want to enqueue an atomic update that consults the previous value of state+props before setting any values. For instance, suppose we wanted to increment a value in state:
|
||||
|
||||
```javascript
|
||||
setState(function(previousState, currentProps) {
|
||||
|
||||
146
docs/docs/ref-02-component-api.zh-CN.md
Normal file
146
docs/docs/ref-02-component-api.zh-CN.md
Normal file
@@ -0,0 +1,146 @@
|
||||
---
|
||||
id: component-api-zh-CN
|
||||
title: 组件 API
|
||||
permalink: component-api-zh-CN.html
|
||||
prev: top-level-api-zh-CN.html
|
||||
next: component-specs-zh-CN.html
|
||||
---
|
||||
|
||||
## React.Component
|
||||
|
||||
当渲染时,React 组件的实例在 React 内部被创建。这些实例在随后的渲染中被重复使用,并可以在组件方法中通过 `this` 访问。唯一的在 React 之外获取 React 组件实例句柄的方法是保存 `React.render` 的返回值。在其它组件内,你可以使用 [refs](/react/docs/more-about-refs-zh-CN.html) 得到相同的结果。
|
||||
|
||||
|
||||
### setState
|
||||
|
||||
```javascript
|
||||
setState(
|
||||
function|object nextState,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
执行一个 nextState 到当前 state 的浅合并。这是你从事件处理器和服务器请求回调用来触发 UI 更新的主要手段。
|
||||
|
||||
第一个参数可以是一个对象(包含0或者多个keys来更新)或者一个(state 和 props的)函数,它返回一个包含要更新的keys的对象。
|
||||
|
||||
这里是一个简单的运用:
|
||||
|
||||
```javascript
|
||||
setState({mykey: 'my new value'});
|
||||
```
|
||||
|
||||
也可以以 `function(state, props)` 传递一个函数。当你想要把一个在设置任何值之前参考前一次 state+props 的值的原子更新放在队列中 这会有很用。例如,假如我们想在 state 增加一个值。
|
||||
|
||||
```javascript
|
||||
setState(function(previousState, currentProps) {
|
||||
return {myInteger: previousState.myInteger + 1};
|
||||
});
|
||||
```
|
||||
|
||||
第二个(可选)的参数是一个将会在 `setState` 完成和组件被重绘后执行的回调函数。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> *绝对不要* 直接改变 `this.state`,因为之后调用 `setState()` 可能会替换掉你做的改变。把 `this.state` 当做是不可变的。
|
||||
>
|
||||
> `setState()` 不会立刻改变 `this.state`,而是创建一个即将处理的 state 转变。在调用该方法之后访问 `this.state` 可能会返回现有的值。
|
||||
>
|
||||
> 对 `setState` 的调用没有任何同步性的保证,并且调用可能会为了性能收益批量执行。
|
||||
>
|
||||
> `setState()` 将总是触发一次重绘,除非在 `shouldComponentUpdate()` 中实现了条件渲染逻辑。如果可变对象被使用了,但又不能在 `shouldComponentUpdate()` 中实现这种逻辑,仅在新 state 和之前的 state 存在差异的时候调用 `setState()` 可以避免不必要的重新渲染。
|
||||
|
||||
|
||||
### replaceState
|
||||
|
||||
```javascript
|
||||
replaceState(
|
||||
object nextState,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
类似于 `setState()`,但是删除任何 先前存在但不在 nextState 里的 state 键。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。它也许会在未来的 React 版本中被完全移除。
|
||||
|
||||
|
||||
### forceUpdate
|
||||
|
||||
```javascript
|
||||
forceUpdate(
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
默认情况下,当你的组件的 state 或者 props 改变,你的组件将会重绘。然而,如果它们隐式的改变(例如:在对象深处的数据改变了但没有改变对象本身)或者如果你的 `render()` 方法依赖于其他的数据,你可以用调用 `forceUpdate()` 来告诉 React 它需要重新运行 `render()`。
|
||||
|
||||
调用 `forceUpdate()` 将会导致 `render()` 跳过 `shouldComponentUpdate()` 在组件上被调用,这会为子级触发正常的生命周期方法。包括每个子级的 `shouldComponentUpdate()` 方法。如果标记改变了,React 仍仅只更新 DOM。
|
||||
|
||||
通常你应该试着避免所有对 `forceUpdate()` 的使用并且在 `render()` 里只从 `this.props` 和 `this.state` 读取。这会使你的组件 "纯粹" 并且你的组件会更简单和高效。
|
||||
|
||||
|
||||
### getDOMNode
|
||||
|
||||
```javascript
|
||||
DOMElement getDOMNode()
|
||||
```
|
||||
|
||||
如果这个组件已经被挂载到了 DOM,它返回相应的浏览器原生的 DOM 元素。这个方法对于读取 DOM 的值很有用,比如表单域的值和执行 DOM 的测量。如果 `render` 返回 `null` 或者 `false` 的时候,`this.getDOMNode()` 返回 `null`。
|
||||
|
||||
> Note:
|
||||
>
|
||||
> getDOMNode 被废弃了,已经被 [React.findDOMNode()] 替换(/react/docs/top-level-api-zh-CN.html#react.finddomnode).
|
||||
>
|
||||
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。它也许会在未来的 React 版本中被完全移除。
|
||||
|
||||
|
||||
### isMounted
|
||||
|
||||
```javascript
|
||||
bool isMounted()
|
||||
```
|
||||
|
||||
如果组件渲染到了 DOM 中,`isMounted()` 返回 true,否则返回 `false`。可以使用该方法来控制对 `setState()` 和 `forceUpdate()` 的异步调用。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。它也许会在未来的 React 版本中被完全移除。
|
||||
|
||||
|
||||
### setProps
|
||||
|
||||
```javascript
|
||||
setProps(
|
||||
object nextProps,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
当和一个外部的 JavaScript 应用整合的时候,你也许会想用 `React.render()` 给 React 组件标示一个改变。
|
||||
|
||||
在根组件上调用 `setProps()` 会改变他的属性并触发一次重绘。另外,你可以提供一个可选的回调函数,一旦 `setProps` 完成并且组件被重绘它就执行。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 如果可能,上述的在同一个节点上再次调用 `React.render()` 的方法是优先替代的。它往往使更新更容易理解。(两种方法并没有显著的性能区别。)
|
||||
>
|
||||
> 这个方法仅能在根组件上被调用。也就是说,它仅在直接传给 `React.render()` 的组件上可用,在它的子级上不可用。如果你倾向于在子组件上使用 `setProps()`,不要利用响应式更新,而是当子组件在 `render()` 中创建的时候传入新的 prop 到子组件中。
|
||||
>
|
||||
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。它也许会在未来的 React 版本中被完全移除。
|
||||
|
||||
### replaceProps
|
||||
|
||||
```javascript
|
||||
replaceProps(
|
||||
object nextProps,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
类似于 `setProps()`,但是删除任何先前存在的 props,而不是合并这两个对象。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。它也许会在未来的 React 版本中被完全移除。
|
||||
@@ -35,8 +35,8 @@ string type
|
||||
|
||||
## Riutilizzo degli eventi
|
||||
|
||||
Gli oggetti `SyntheticEvent` sono gestiti come un pool. Ciò significa che ciascun oggetto `SyntheticEvent` sarà riutilizzato e tutte le sue proprietà annullate dopo che la callback dell'evento è stata invocata.
|
||||
Ciò avviene per ragioni di performance.
|
||||
Gli oggetti `SyntheticEvent` sono gestiti come un pool. Ciò significa che ciascun oggetto `SyntheticEvent` sarà riutilizzato e tutte le sue proprietà annullate dopo che la callback dell'evento è stata invocata.
|
||||
Ciò avviene per ragioni di performance.
|
||||
Per questo motivo non potrai accedere all'evento in maniera asincrona.
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -35,8 +35,8 @@ string type
|
||||
|
||||
## Event pooling
|
||||
|
||||
The `SyntheticEvent` is pooled. This means that the `SyntheticEvent` object will be reused and all properties will be nullified after the event callback has been invoked.
|
||||
This is for performance reasons.
|
||||
The `SyntheticEvent` is pooled. This means that the `SyntheticEvent` object will be reused and all properties will be nullified after the event callback has been invoked.
|
||||
This is for performance reasons.
|
||||
As such, you cannot access the event in an asynchronous way.
|
||||
|
||||
```javascript
|
||||
@@ -82,6 +82,22 @@ DOMDataTransfer clipboardData
|
||||
```
|
||||
|
||||
|
||||
### Composition Events
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onCompositionEnd onCompositionStart onCompositionUpdate
|
||||
```
|
||||
|
||||
Properties:
|
||||
|
||||
```javascript
|
||||
string data
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Keyboard Events
|
||||
|
||||
Event names:
|
||||
@@ -166,6 +182,15 @@ boolean shiftKey
|
||||
```
|
||||
|
||||
|
||||
### Selection events
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onSelect
|
||||
```
|
||||
|
||||
|
||||
### Touch events
|
||||
|
||||
Event names:
|
||||
|
||||
@@ -56,7 +56,7 @@ DOMDataTransfer clipboardData
|
||||
```
|
||||
|
||||
|
||||
### 键盘事件
|
||||
### 键盘事件
|
||||
|
||||
事件名称:
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ In order to do a tree diff, we first need to be able to diff two nodes. There ar
|
||||
|
||||
### Different Node Types
|
||||
|
||||
If the node type is different, React is going to treat them as two different sub-trees, throw away the first one and build/insert the second one.
|
||||
If the node type is different, React is going to treat them as two different sub-trees, throw away the first one and build/insert the second one.
|
||||
|
||||
```xml
|
||||
renderA: <div />
|
||||
|
||||
147
docs/docs/thinking-in-react.zh-CN.md
Normal file
147
docs/docs/thinking-in-react.zh-CN.md
Normal file
@@ -0,0 +1,147 @@
|
||||
---
|
||||
id: thinking-in-react-zh-CN
|
||||
title: React 编程思想
|
||||
prev: tutorial-zh-CN.html
|
||||
next: conferences-zh-CN.html
|
||||
redirect_from: 'blog/2013/11/05/thinking-in-react.html'
|
||||
---
|
||||
|
||||
by Pete Hunt
|
||||
|
||||
在我看来,React 是构建大型,快速 web app 的首选方式。它已经在 Facebook 和 Instagram 被我们有了广泛的应用。
|
||||
|
||||
React许多优秀的部分之一是它如何使你随着构建 app 来思考 app。在本文里,我将带领你学习一个用 React 构建可搜索的数据表的思考过程。
|
||||
|
||||
## 从模型(mock)开始
|
||||
|
||||
想象我们已经有个一个 JSON API 和一个来自设计师的模型。我们的设计师似乎不是很好因为模型看起来像是这样:
|
||||
|
||||

|
||||
|
||||
我们的 JSON API 返回一些看起来像这样的数据:
|
||||
|
||||
```
|
||||
[
|
||||
{category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
|
||||
{category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
|
||||
{category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
|
||||
{category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
|
||||
{category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
|
||||
{category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
|
||||
];
|
||||
```
|
||||
|
||||
## 第一步:把UI拆分为一个组件的层级
|
||||
|
||||
首先你想要做的是在模型里的每一个组建周围绘制边框并给他们命名。如果你和设计师一起工作,他们应该已经完成这步了,所以去和他们谈谈!他们的photoshop图层名也许最终会成为你的React组件名。
|
||||
|
||||
但是你如何知道什么东西应该是独立的组件?只需使用你决定是否创建一个函数或者对象的相同技术。这样一种技术是[single responsibility principle](https://en.wikipedia.org/wiki/Single_responsibility_principle),即是,一个组件在理想情况下只做一件事情。如果它最终变大,它就应该被分解为更小的组件。
|
||||
|
||||
既然你频繁显示一个JSON的数据模型给用户,你会发现,如果你的模型构建正确,你的UI(因此也有你的组件结构)就将映射良好.那是因为UI和数据模型趋向于附着于相同的 *信息架构*,这意味着把你的 UI 分离为组件的工作通常是简单的,只需把他拆成精确对应代表你的数据模型的每一块的组件.
|
||||
|
||||

|
||||
|
||||
在这里你会看到,在我们简单的APP里有五个组件.我用斜体表示每个组件的数据.
|
||||
|
||||
1. **`FilterableProductTable` (orange):** 包含示例的整体
|
||||
2. **`SearchBar` (blue):** 接受所有 *用户输入*
|
||||
3. **`ProductTable` (green):** 基于 *用户输入* 显示和过滤 *数据集合(data collection)*
|
||||
4. **`ProductCategoryRow` (turquoise):** 为每个 *分类* 显示一个列表头
|
||||
5. **`ProductRow` (red):** 为每个 *产品* 显示一个行
|
||||
|
||||
如果你看着 `ProductTable`,你会看到表的头(包含了 "Name" 和 "Price" 标签) 不是独立的组件.这是一个个人喜好问题,并且无论哪种方式都有争论.对于这个例子,我把它留做 `ProductTable` 的一部分,因为它是 *data collection*渲染的一部分,而 *data collection*渲染是 `ProductTable` 的职责.然而,当列表头增长到复杂的时候(例如 如果我们添加排序的功能性),那么无疑的使它成为独立的 `ProductTableHeader` 组件是有意义的.
|
||||
|
||||
既然现在我们已经识别出了我们模型中的组件,让我们把他们安排到一个层级中.这很容易. 在模型中出现在其他组件中的组件 同样应该在层级中表现为一个子级:
|
||||
|
||||
* `FilterableProductTable`
|
||||
* `SearchBar`
|
||||
* `ProductTable`
|
||||
* `ProductCategoryRow`
|
||||
* `ProductRow`
|
||||
|
||||
## Step 2: 用React创建一个静态版本
|
||||
|
||||
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/yun1vgqb/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
|
||||
|
||||
既然你已经有了你的组件层级,时候实现你的app了.简单的方式是构建一个版本,它采取你的数据模型并渲染UI但是没有互动性.最好是分离这些过程,因为构建一个静态版本需要无脑的打很多字,然而添加互动性需要很多思考但不需要打太多字.我们会看到是为什么:
|
||||
|
||||
要构建一个渲染你的数据模型的 app 的静态版本,你会想构建一个重用其他组件并利用 *props* 传递数据的组件. *props* 是一种从父级传递数据到子级的方式.如果你对 *state* 的观念很熟悉, **绝不要用state** 来构建这个静态版本.State 仅仅是为互动预留的,即,随时间变化的数据. 因为这是一个静态版本的app,你不需要它.
|
||||
|
||||
你可以自顶向下或自底向上的构建.也就是说,你可以既从较高的层级(如 从 `FilterableProductTable` 开始) 也可以从较低的层级(`ProductRow`)开始构建组件. 在较简单的例子里,通常自顶向下要容易一些,然而在更大的项目上 自底向上更容易,并且伴随着构建写测试较容易.
|
||||
|
||||
在这一步的最后,你会有一个渲染你数据模型的可重用的组件库. 这些组件将只含有 `render()` 方法因为这是一个你的app的静态版本. 在层级顶端的组件 (`FilterableProductTable`) 将会接受你的数据模型作为一个prop.如果你对你的底层数据模型做了变化并且再次调用 `React.render()` ,UI将会更新.很容易看到你的UI是如何更新以及哪里来作出变动,因为这里没有任何复杂的事情发生. React的 **单向数据流** (也被称为 *单向绑定* )保持了每个东西模块化和快速.
|
||||
|
||||
如果你执行这步需要帮助,请参考 [React docs](/react/docs/) .
|
||||
|
||||
### 小插曲: props vs state
|
||||
|
||||
在React里有两种数据 "模型":props和state.明白这二者之间的区别是很重要的;如果你不是很确定不同是什么,请概览[React官方文档](/react/docs/interactivity-and-dynamic-uis-zh-CN.html)
|
||||
|
||||
## 第三步:确定最小(但完备)的 UI state 的表达
|
||||
|
||||
要让你的UI互动,你需要能够触发变化到你的底层数据模型上.React用 **state** 来让此变得容易.
|
||||
|
||||
要正确的构建你的app,你首先需要思考你的app需要的可变state的最小组. 这里的关键是 DRY: *Don't Repeat Yourself(不要重复自己)*.想出哪些是你的应用需要的绝对最小 state 表达,并按需计算其他任何数据.例如,如果你要构建一个 TODO list,只要保持一个 TODO 项的数组;不要为了计数保持一个单独的 state 变量.作为替代,当你想渲染 TODO 数量时,简单的采用TODO项目数组的长度.
|
||||
|
||||
考虑我们例子应用中数据的所有块.我们有:
|
||||
|
||||
* 原始的产品列表
|
||||
* 用户输入的搜索文本
|
||||
* checkbox的值
|
||||
* 产品的滤过的列表
|
||||
|
||||
让我们遍历每一个并指出哪一个是state.简单的问三个关于每个数据块的问题:
|
||||
|
||||
1. 它是通过props从父级传递来的吗?如果是,它可能不是state.
|
||||
2. 它随时间变化吗?如果不是,它可能不是state.
|
||||
3. 你能基于其他任何组件里的 state 或者 props 计算出它吗?如果是,它可能不是state.
|
||||
|
||||
原始的产品列表被以 props 传入,所以它不是 state. 搜索文本和 checkbox 看起来是state 因为他们随时间变化并且不能从任何东西计算出.最后,产品滤过的列表不是state因为它可以联合原始列表与搜索文本及 checkbox 的值计算出.
|
||||
|
||||
所以最后,我们的 state 是:
|
||||
|
||||
* 用户输入的搜索文本
|
||||
* checkbox 的值
|
||||
|
||||
## 第四步:确定你的 state 应该存在于哪里
|
||||
|
||||
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/zafjbw1e/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
|
||||
|
||||
好,我们已经确定了app state 的最小组是什么.接下来,我们需要确定哪个组件变动,或者 *拥有*,这 个state.
|
||||
|
||||
记住:React都是关于单向数据流下组件层级的.可能不能立刻明白哪些组件应该拥有哪些 state. **这常常对于新手在理解上是最具挑战的一部分,** 所以跟着这几步来弄明白它:
|
||||
|
||||
对于你的应用里每一个数据块:
|
||||
|
||||
* 基于 state 确定每个绘制某些东西的组件
|
||||
* 找到一个共同拥有者的组件(在层级中所有组件之上需要这个state的单个组件)
|
||||
* 要么是共同拥有者,要么是其他在层级里更高级的组件应该拥有这个state
|
||||
* 如果你不能找到一个组件,它拥有这个state有意义,创建一个新的组件简单的为了持有此state,并把它在层级里添加比共同拥有者组件更高的层级上.
|
||||
|
||||
让我们过一遍这个用于我们应用的策略:
|
||||
|
||||
* `ProductTable` 需要基于 state 过滤产品列表,`SearchBar` 需要显示搜索文本和选择状态.
|
||||
* 共同拥有者组件是`FilterableProductTable` .
|
||||
* 对于过滤文本和选择值存在于 `FilterableProductTable` 观念上是有意义的.
|
||||
|
||||
酷,我们已经决定了我们的state存在于 `FilterableProductTable` .首先,添加一个 `getInitialState()` 方法到 `FilterableProductTable` ,返回 `{filterText: '', inStockOnly: false}` 来反映你的应用的初始状态. 然后,传递`filterText` 和 `inStockOnly` 给 `ProductTable` 和`SearchBar` 作为prop.最后,使用这些prop来过滤 `ProductTable` 中的行和设置`SearchBar`的表单项的值.
|
||||
|
||||
你可以开始看看你的应用将有怎样的行为: 设置 `filterText` 为 `"ball"` 并刷新你的app.你将看到数据表被正确更新了.
|
||||
|
||||
## 第五步:添加反向数据流
|
||||
|
||||
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/n47gckhr/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
|
||||
|
||||
到目前为止,我们已经构建了一个应用, 它以props 和 state 沿着层级向下流动的功能正确渲染。现在是时候支持数据的另一种流动了:在层级深处的表单组件需要更新 `FilterableProductTable` 里的state.
|
||||
|
||||
React 让数据显式流动,使理解你的应用如何工作变得简单,但是相对于传统的双向数据绑定,确实需要打多一些的字。 React 提供了一个叫做 `ReactLink` 的插件来使这种模式和双向数据绑定一样方便,但是考虑到这篇文章的目的,我们将会保持所有东西都直截了当。
|
||||
|
||||
如果你尝试在当前版本的示例中输入或者选中复选框,你会发现 React 忽略了你的输入。这是有意的,因为已经设置了 `input` 的 `value` prop 总是与 `FilterableProductTable` 传递过来的 `state` 一致。
|
||||
|
||||
让我们思考下我们希望发生什么。我们想确保每当用户改变了表单,我们就更新 state 来反映用户的输入。由于组件应该只更新自己拥有的 state , `FilterableProductTable` 将会传递一个回调函数给 `SearchBar` ,此函数每当 state 应被改变时就会击发。我们可以使用 input 的 `onChange` 事件来接受它的通知。 `FilterableProductTable` 传递的回调函数将会调用 `setState()` ,然后应用将会被更新。
|
||||
|
||||
虽然这听起来复杂,但是实际上只是数行代码。并且数据在应用中从始至终如何流动是非常明确的。
|
||||
|
||||
## 好了,就是这样
|
||||
|
||||
希望,这给了你一个怎样思考用React构建组件和应用的概念。虽然可能比你通常要输入更多的代码,记住,读代码的时间远比写代码的时间多,并且阅读这种模块化的,显式的代码是极端容易的。当你开始构建大型组件库时,你会非常感激这种清晰性和模块化,并且随着代码的重用,你的代码行数将会开始缩减. :)。
|
||||
@@ -41,6 +41,7 @@ Per questo tutorial renderemo il tutto il più semplice possibile. Incluso nel p
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
</head>
|
||||
@@ -220,12 +221,13 @@ Il Markdown è una maniera semplice di formattare il tuo testo in linea. Ad esem
|
||||
|
||||
Per prima cosa, aggiungiamo la libreria di terze parti **marked** alla tua applicazione. Questa è una libreria JavaScript che prende il testo Markdown e lo converte in HTML nativo. Per fare ciò è richiesto un tag script nel tag head (che abbiamo già incluso nel playground React):
|
||||
|
||||
```html{8}
|
||||
```html{9}
|
||||
<!-- index.html -->
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script>
|
||||
|
||||
@@ -42,6 +42,7 @@ next: thinking-in-react-ja-JP.html
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
</head>
|
||||
@@ -217,12 +218,13 @@ Markdown はインラインでテキストをフォーマットする簡単な
|
||||
|
||||
まず最初に、サードパーティ製の **marked** ライブラリをアプリケーションに追加します。 marked は Markdown テキストを生の HTML に変換する JavaScript ライブラリです。 既にある head タグの内側に script タグを書き込み、以下のように marked を読み込ませます。
|
||||
|
||||
```html{8}
|
||||
```html{9}
|
||||
<!-- index.html -->
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script>
|
||||
@@ -339,7 +341,7 @@ var CommentList = React.createClass({
|
||||
```javascript{3}
|
||||
// tutorial11.js
|
||||
ReactDOM.render(
|
||||
<CommentBox url="comments.json" />,
|
||||
<CommentBox url="api/comments" />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
```
|
||||
|
||||
@@ -42,6 +42,7 @@ next: thinking-in-react-ko-KR.html
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
</head>
|
||||
@@ -220,12 +221,13 @@ Markdown은 텍스트를 포맷팅하는 간단한 방식입니다. 예를 들
|
||||
|
||||
먼저 서드파티 라이브러리인 **marked**를 애플리케이션에 추가합니다. 이 JavaScript 라이브러리는 Markdown 텍스트를 HTML 문법으로 변환해줍니다. head 태그안에 스크립트 태그를 추가해 주세요. (React playground에는 이미 포함되어 있습니다):
|
||||
|
||||
```html{8}
|
||||
```html{9}
|
||||
<!-- index.html -->
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script>
|
||||
|
||||
@@ -260,7 +260,7 @@ But there's a problem! Our rendered comments look like this in the browser: "`<p
|
||||
|
||||
That's React protecting you from an [XSS attack](https://en.wikipedia.org/wiki/Cross-site_scripting). There's a way to get around it but the framework warns you not to use it:
|
||||
|
||||
```javascript{4,10}
|
||||
```javascript{4,14}
|
||||
// tutorial7.js
|
||||
var Comment = React.createClass({
|
||||
rawMarkup: function() {
|
||||
|
||||
714
docs/docs/tutorial.zh-CN.md
Normal file
714
docs/docs/tutorial.zh-CN.md
Normal file
@@ -0,0 +1,714 @@
|
||||
---
|
||||
id: tutorial-zh-CN
|
||||
title: 教程
|
||||
prev: getting-started-zh-CN.html
|
||||
next: thinking-in-react-zh-CN.html
|
||||
---
|
||||
|
||||
我们将建立一个你可以放进博客的简单却真实的评论框,一个 Disqus、LiveFyre 或 Facebook comments 提供的实时评论的基础版本。
|
||||
|
||||
我们将提供:
|
||||
|
||||
* 一个所有评论的视图
|
||||
* 一个用于提交评论的表单
|
||||
* 为你提供制定后台的挂钩(Hooks)
|
||||
|
||||
同时也会有一些简洁的功能:
|
||||
|
||||
* **优化的评论:** 评论在它们保存到服务器之前就显示在列表里,所以感觉很快。
|
||||
* **实时更新:** 其他用户的评论被实时浮现到评论中。
|
||||
* **Markdown格式化:** 用户可以用Markdown格式化它们的文字。
|
||||
|
||||
### 想要跳过所有内容,只查看源代码?
|
||||
|
||||
[全在 GitHub .](https://github.com/reactjs/react-tutorial)
|
||||
|
||||
### 运行服务器
|
||||
|
||||
为了开始本教程,我们将要需要一个运行着的服务器。这将是我们纯粹用来获取和保存数据的伺服终端。为了让这尽可能的容易,我们已经用许多不同的语言编写了简单的服务器,它正好完成我们需要的事。 **你可以[查看源代码](https://github.com/reactjs/react-tutorial/) 或者 [下载 zip 文件](https://github.com/reactjs/react-tutorial/archive/master.zip) 包括了所有你开始学习需要的东西**
|
||||
|
||||
为了简单起见,我们将要运行的服务器使用 `JSON` 文件作为数据库。你不会在生产环境运行这个,但是它让我们更容易模拟使用一个API时你可能会做的事。一旦你启动服务器,它将会支持我们的API终端,同时也将伺服我们需要的静态页面。
|
||||
|
||||
### 开始
|
||||
|
||||
对于此教程,我们将使它尽可能的容易。被包括在上面讨论的服务器包里的是一个我们将在其中工作的 HTML 文件。在你最喜欢的编辑器里打开 `public/index.html`。它应该看起来像这样 (可能有一些小的不同,稍后我们将添加一个额外的 `<script>` 标签):
|
||||
|
||||
```html
|
||||
<!-- index.html -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
<script type="text/babel" src="scripts/example.js"></script>
|
||||
<script type="text/babel">
|
||||
// To get started with this tutorial running your own code, simply remove
|
||||
// the script tag loading scripts/example.js and start writing code here.
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
在本教程剩余的部分,我们将在此 script 标签中编写我们的 JavaScript 代码。我们没有任何高级的实时加载所以在保存以后你需要刷新你的浏览器来观察更新。通过在浏览器打开 `http://localhost:3000` 关注你的进展。当你没有任何修改第一次加载时,你将看到我们将要准备建立的已经完成的产品。当你准备开始工作,请删除前面的 `<script>` 标签然后你就可以继续了。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 我们在这里引入 jQuery 是因为我们想简化我们未来的 ajax 请求,但这对React的正常工作 **不是** 必要的。
|
||||
|
||||
### 你的第一个组件
|
||||
|
||||
React 中都是关于模块化、可组装的组件。以我们的评论框为例,我们将有如下的组件结构:
|
||||
|
||||
```
|
||||
- CommentBox
|
||||
- CommentList
|
||||
- Comment
|
||||
- CommentForm
|
||||
```
|
||||
|
||||
让我们构造 `CommentBox` 组件,仅是一个简单的 `<div>` :
|
||||
|
||||
```javascript
|
||||
// tutorial1.js
|
||||
var CommentBox = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentBox">
|
||||
Hello, world! I am a CommentBox.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
React.render(
|
||||
<CommentBox />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
```
|
||||
|
||||
注意原生的HTML元素以小写开头,而制定的 React 类以大写开头。
|
||||
|
||||
#### JSX 语法
|
||||
|
||||
首先你会注意到你的 JavaScript 中 XML 式的语法。我们有一个简单的预编译器,将这种语法糖转换成单纯的 JavaScript :
|
||||
|
||||
```javascript
|
||||
// tutorial1-raw.js
|
||||
var CommentBox = React.createClass({displayName: 'CommentBox',
|
||||
render: function() {
|
||||
return (
|
||||
React.createElement('div', {className: "commentBox"},
|
||||
"Hello, world! I am a CommentBox."
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
React.render(
|
||||
React.createElement(CommentBox, null),
|
||||
document.getElementById('content')
|
||||
);
|
||||
```
|
||||
|
||||
它的使用是可选的,但是我们发现 JSX 语法比单纯的 JavaScript 更加容易使用。阅读更多关于[JSX 语法的文章](/react/docs/jsx-in-depth-zh-CN.html)。
|
||||
|
||||
#### What's going on
|
||||
|
||||
我们在一个 JavaScript 对象中传递一些方法到 `React.createClass()` 来创建一个新的React组件。这些方法中最重要的是 `render`,该方法返回一颗 React 组件树,这棵树最终将会渲染成 HTML。
|
||||
|
||||
这个 `<div>` 标签不是真实的DOM节点;他们是 React `div` 组件的实例化。你可以把这些看做是React知道如何处理的标记或者是一些数据 。React 是**安全的**。我们不生成 HTML 字符串,因此XSS防护是默认特性。
|
||||
|
||||
你没有必要返回基本的 HTML。你可以返回一个你(或者其他人)创建的组件树。这就使 React **组件化**:一个可维护前端的关键原则。
|
||||
|
||||
`React.render()` 实例化根组件,启动框架,注入标记到原始的 DOM 元素中,作为第二个参数提供。
|
||||
|
||||
## 组合组件
|
||||
|
||||
让我们为 `CommentList` 和 `CommentForm` 建造骨架,它们将会,再一次的,是一些简单的 `<div>`。添加这两个组件到你的文件里,保持现存的 `CommentBox` 声明和 `React.render` 调用:
|
||||
|
||||
```javascript
|
||||
// tutorial2.js
|
||||
var CommentList = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentList">
|
||||
Hello, world! I am a CommentList.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var CommentForm = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentForm">
|
||||
Hello, world! I am a CommentForm.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
接着,更新 `CommentBox` 以使用这些新的组件:
|
||||
|
||||
```javascript{6-8}
|
||||
// tutorial3.js
|
||||
var CommentBox = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList />
|
||||
<CommentForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
注意我们是如何混合 HTML 标签和我们建立的组件。HTML 组件是正常的 React 组件,就和你定义的一样,只有一个区别。JSX 编译器会自动重写 HTML 标签为 `React.createElement(tagName)` 表达式,其它什么都不做。这是为了避免污染全局命名空间。
|
||||
|
||||
### 使用 props
|
||||
|
||||
让我们创建 `Comment` 组件,它将依赖于从父级传来的数据。从父级传来的数据在子组件里作为 '属性' 可供使用。 这些 '属性' 可以通过 `this.props` 访问。使用属性,我们将能读取从 `CommentList` 传递给 `Comment` 的数据,并且渲染一些标记:
|
||||
|
||||
```javascript
|
||||
// tutorial4.js
|
||||
var Comment = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="comment">
|
||||
<h2 className="commentAuthor">
|
||||
{this.props.author}
|
||||
</h2>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
在 JSX 中,通过将 JavaScript 表达式放在大括号中(作为属性或者子节点),你可以把文本或者 React 组件放置到树中。我们以 `this.props` 的 keys 访问传递给组件的命名属性,以 `this.props.children` 访问任何嵌套的元素。
|
||||
|
||||
### 组件的属性
|
||||
|
||||
既然我们已经定义了 `Comment` 组件,我们将要传递作者名和评论文字给它。这允许我们为每个评论重用相同的代码。现在让我们在我们的 `CommentList` 里添加一些评论。
|
||||
|
||||
```javascript{6-7}
|
||||
// tutorial5.js
|
||||
var CommentList = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentList">
|
||||
<Comment author="Pete Hunt">This is one comment</Comment>
|
||||
<Comment author="Jordan Walke">This is *another* comment</Comment>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
注意,我们已经从 `CommentList` 组件传递了一些数据到 `Comment` 组件。例如,我们传递了 *Pete Hunt* (通过属性)和 *This is one comment* (通过 XML-风格的子节点)给第一个 `Comment`。如上面提到的那样, `Comment` 组件将会通过 `this.props.author` 和 `this.props.children` 访问 这些 '属性'。
|
||||
|
||||
### 添加 Markdown
|
||||
|
||||
Markdown 是一种简单的内联格式化你的文字的方法。例如,用星号包围文本将会使其强调突出。
|
||||
|
||||
首先,添加第三方库 **marked** 到你的应用。这是一个JavaScript库,接受 Markdown 文本并且转换为原始的 HTML。这需要在你的头部有一个 script 标签(那个我们已经在 React 操场上包含了的标签):
|
||||
|
||||
```html{9}
|
||||
<!-- index.html -->
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script>
|
||||
</head>
|
||||
```
|
||||
|
||||
然后,让我们转换评论文本为 Markdown 并输出它:
|
||||
|
||||
```javascript{9}
|
||||
// tutorial6.js
|
||||
var Comment = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="comment">
|
||||
<h2 className="commentAuthor">
|
||||
{this.props.author}
|
||||
</h2>
|
||||
{marked(this.props.children.toString())}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
我们在这里唯一做的就是调用 marked 库。我们需要把 从 React 的包裹文本来的 `this.props.children` 转换成 marked 能理解的原始字符串,所以我们显示地调用了`toString()`。
|
||||
|
||||
但是这里有一个问题!我们渲染的评论在浏览器里看起来像这样: "`<p>`This is `<em>`another`</em>` comment`</p>`" 。我们想让这些标签真正地渲染为 HTML。
|
||||
|
||||
那是 React 在保护你免受 [XSS 攻击](https://en.wikipedia.org/wiki/Cross-site_scripting)。有一个方法解决这个问题,但是框架会警告你别使用这种方法:
|
||||
|
||||
```javascript{4,10}
|
||||
// tutorial7.js
|
||||
var Comment = React.createClass({
|
||||
rawMarkup: function() {
|
||||
var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
|
||||
return { __html: rawMarkup };
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="comment">
|
||||
<h2 className="commentAuthor">
|
||||
{this.props.author}
|
||||
</h2>
|
||||
<span dangerouslySetInnerHTML={this.rawMarkup()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
这是一个特殊的 API,故意让插入原始的 HTML 变得困难,但是对于 marked 我们将利用这个后门。
|
||||
|
||||
**记住:** 使用这个功能你会依赖于 marked 是安全的。既然如此,我们传递 `sanitize: true` 告诉 marked escape 源码里任何的 HTML 标记,而不是直接不变的让他们通过。
|
||||
|
||||
### 挂钩数据模型
|
||||
|
||||
到目前为止我们已经完成了在源码里直接插入评论。作为替代,让我们渲染一团 JSON 数据到评论列表里。最终数据将会来自服务器,但是现在,写在你的源代码中:
|
||||
|
||||
```javascript
|
||||
// tutorial8.js
|
||||
var data = [
|
||||
{author: "Pete Hunt", text: "This is one comment"},
|
||||
{author: "Jordan Walke", text: "This is *another* comment"}
|
||||
];
|
||||
```
|
||||
|
||||
我们需要以一种模块化的方式将这个数据传入到 `CommentList`。修改 `CommentBox` 和 `React.render()` 方法,以通过 props 传入数据到 `CommentList`:
|
||||
|
||||
```javascript{7,15}
|
||||
// tutorial9.js
|
||||
var CommentBox = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.props.data} />
|
||||
<CommentForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.render(
|
||||
<CommentBox data={data} />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
```
|
||||
|
||||
既然现在数据在 `CommentList` 中可用了,让我们动态地渲染评论:
|
||||
|
||||
```javascript{4-10,13}
|
||||
// tutorial10.js
|
||||
var CommentList = React.createClass({
|
||||
render: function() {
|
||||
var commentNodes = this.props.data.map(function (comment) {
|
||||
return (
|
||||
<Comment author={comment.author}>
|
||||
{comment.text}
|
||||
</Comment>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div className="commentList">
|
||||
{commentNodes}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
就是这样!
|
||||
|
||||
### 从服务器获取数据
|
||||
|
||||
让我们用一些来自服务器的动态数据替换硬编码的数据。我们将移除数据的prop,用获取数据的URL来替换它:
|
||||
|
||||
```javascript{3}
|
||||
// tutorial11.js
|
||||
React.render(
|
||||
<CommentBox url="/api/comments" />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
```
|
||||
|
||||
这个组件不同于和前面的组件,因为它必须重新渲染自己。该组件将不会有任何数据,直到请求从服务器返回,此时该组件或许需要渲染一些新的评论。
|
||||
|
||||
注意: 此代码在这个阶段不会工作。
|
||||
|
||||
### Reactive state
|
||||
|
||||
迄今为止,基于它自己的props,每个组件都渲染了自己一次。`props` 是不可变的:它们从父级传来并被父级“拥有”。为了实现交互,我们给组件引进了可变的 **state**。`this.state` 是组件私有的,可以通过调用 `this.setState()` 改变它。每当state更新,组件就重新渲染自己。
|
||||
|
||||
`render()` 方法被声明为一个带有 `this.props` 和 `this.state` 的函数。框架保证了 UI 总是与输入一致。
|
||||
|
||||
当服务器获取数据时,我们将会改变我们已有的评论数据。让我们给 `CommentBox` 组件添加一组评论数据作为它的状态:
|
||||
|
||||
```javascript{3-5,10}
|
||||
// tutorial12.js
|
||||
var CommentBox = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
`getInitialState()` 在生命周期里只执行一次,并设置组件的初始状态。
|
||||
|
||||
#### 更新状态
|
||||
当组件第一次创建时,我们想从服务器获取一些 JSON 并且更新状态以反映最新的数据。我们将用 jQuery 来发送一个异步请求到我们刚才启动的服务器以获取我们需要的数据。看起来像这样:
|
||||
|
||||
```json
|
||||
[
|
||||
{"author": "Pete Hunt", "text": "This is one comment"},
|
||||
{"author": "Jordan Walke", "text": "This is *another* comment"}
|
||||
]
|
||||
```
|
||||
|
||||
```javascript{6-18}
|
||||
// tutorial13.js
|
||||
var CommentBox = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this),
|
||||
error: function(xhr, status, err) {
|
||||
console.error(this.props.url, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
这里, `componentDidMount` 是一个当组件被渲染时被React自动调用的方法。动态更新的关键是对 `this.setState()` 的调用。我们用新的从服务器来的替换掉旧的评论组,然后UI自动更新自己。因为这种反应性,仅是一个微小的变化就添加了实时更新。我们这里将用简单的轮询,但是你可以容易的使用 WebSockets 或者其他技术。
|
||||
|
||||
```javascript{3,15,20-21,35}
|
||||
// tutorial14.js
|
||||
var CommentBox = React.createClass({
|
||||
loadCommentsFromServer: function() {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this),
|
||||
error: function(xhr, status, err) {
|
||||
console.error(this.props.url, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.loadCommentsFromServer();
|
||||
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.render(
|
||||
<CommentBox url="/api/comments" pollInterval={2000} />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
我们在这里做的全部事情是把 AJAX 调用移动到独立的方法里,然后在组件第一次加载时及其后每2秒 调用它。试着在你的浏览器里运行它并且改变 `comments.json` 文件(在你的服务器的相同目录);2秒内,变化将会显现!
|
||||
|
||||
### 添加新评论
|
||||
|
||||
现在是时候建立表单了,我们的 `CommentForm` 组件应该询问用户他们的名字和评论文本然后发送一个请求到服务器来保存评论.
|
||||
|
||||
```javascript{5-9}
|
||||
// tutorial15.js
|
||||
var CommentForm = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<form className="commentForm">
|
||||
<input type="text" placeholder="Your name" />
|
||||
<input type="text" placeholder="Say something..." />
|
||||
<input type="submit" value="Post" />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
让我们做一个交互式的表单。当用户提交表单时,我们应该清空它,提交一个请求给服务器,和刷新评论列表。要开始,让我们监听表单的提交事件并清空它。
|
||||
|
||||
```javascript{3-14,16-19}
|
||||
// tutorial16.js
|
||||
var CommentForm = React.createClass({
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var author = React.findDOMNode(this.refs.author).value.trim();
|
||||
var text = React.findDOMNode(this.refs.text).value.trim();
|
||||
if (!text || !author) {
|
||||
return;
|
||||
}
|
||||
// TODO: send request to the server
|
||||
React.findDOMNode(this.refs.author).value = '';
|
||||
React.findDOMNode(this.refs.text).value = '';
|
||||
return;
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<form className="commentForm" onSubmit={this.handleSubmit}>
|
||||
<input type="text" placeholder="Your name" ref="author" />
|
||||
<input type="text" placeholder="Say something..." ref="text" />
|
||||
<input type="submit" value="Post" />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
##### 事件
|
||||
|
||||
React使用驼峰命名规范(camelCase)给组件绑定事件处理器。我们给表单绑定一个`onSubmit`处理器,它在表单提交了合法的输入后清空表单字段。
|
||||
|
||||
在事件中调用`preventDefault()`来阻止浏览器提交表单的默认行为。
|
||||
|
||||
##### Refs
|
||||
|
||||
我们利用`ref`属性给子组件赋予名字,`this.refs`-引用组件。我们可以在组件上调用 `React.findDOMNode(component)` 获取原生的浏览器DOM元素。
|
||||
|
||||
##### 回调函数作为属性
|
||||
|
||||
当用户提交评论时,我们需要刷新评论列表来包含这条新评论。在`CommentBox`中完成所有逻辑是有道理的,因为`CommentBox` 拥有代表了评论列表的状态(state)。
|
||||
|
||||
我们需要从子组件传回数据到它的父组件。我们在父组件的`render`方法中以传递一个新的回调函数(`handleCommentSubmit`)到子组件完成这件事,绑定它到子组件的 `onCommentSubmit` 事件上。无论事件什么时候触发,回调函数都将被调用:
|
||||
|
||||
```javascript{16-18,31}
|
||||
// tutorial17.js
|
||||
var CommentBox = React.createClass({
|
||||
loadCommentsFromServer: function() {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this),
|
||||
error: function(xhr, status, err) {
|
||||
console.error(this.props.url, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
handleCommentSubmit: function(comment) {
|
||||
// TODO: submit to the server and refresh the list
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.loadCommentsFromServer();
|
||||
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
当用户提交表单时,让我们从 `CommentForm` 调用这个回调函数:
|
||||
|
||||
```javascript{10}
|
||||
// tutorial18.js
|
||||
var CommentForm = React.createClass({
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var author = React.findDOMNode(this.refs.author).value.trim();
|
||||
var text = React.findDOMNode(this.refs.text).value.trim();
|
||||
if (!text || !author) {
|
||||
return;
|
||||
}
|
||||
this.props.onCommentSubmit({author: author, text: text});
|
||||
React.findDOMNode(this.refs.author).value = '';
|
||||
React.findDOMNode(this.refs.text).value = '';
|
||||
return;
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<form className="commentForm" onSubmit={this.handleSubmit}>
|
||||
<input type="text" placeholder="Your name" ref="author" />
|
||||
<input type="text" placeholder="Say something..." ref="text" />
|
||||
<input type="submit" value="Post" />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
既然现在回调函数已经就绪,我们所需要做的就是提交到服务器然后刷新列表:
|
||||
|
||||
```javascript{17-28}
|
||||
// tutorial19.js
|
||||
var CommentBox = React.createClass({
|
||||
loadCommentsFromServer: function() {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this),
|
||||
error: function(xhr, status, err) {
|
||||
console.error(this.props.url, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
handleCommentSubmit: function(comment) {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
data: comment,
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this),
|
||||
error: function(xhr, status, err) {
|
||||
console.error(this.props.url, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.loadCommentsFromServer();
|
||||
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 优化: 优化的更新
|
||||
|
||||
我们的应用现在已经功能完备,但是它感觉很慢,因为在评论出现在列表前必须等待请求完成。我们可以优化添加这条评论到列表以使应用感觉更快。
|
||||
|
||||
```javascript{17-19}
|
||||
// tutorial20.js
|
||||
var CommentBox = React.createClass({
|
||||
loadCommentsFromServer: function() {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this),
|
||||
error: function(xhr, status, err) {
|
||||
console.error(this.props.url, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
handleCommentSubmit: function(comment) {
|
||||
var comments = this.state.data;
|
||||
var newComments = comments.concat([comment]);
|
||||
this.setState({data: newComments});
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
data: comment,
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this),
|
||||
error: function(xhr, status, err) {
|
||||
console.error(this.props.url, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.loadCommentsFromServer();
|
||||
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 祝贺!
|
||||
|
||||
你刚刚通过几个简单的步骤建立了一个评论框。学习更多关于[为什么使用 React](/react/docs/why-react-zh-CN.html), 或者深入 [API 参考](/react/docs/top-level-api.html) 开始钻研!祝你好运!
|
||||
@@ -4,7 +4,7 @@ title: Downloads
|
||||
layout: single
|
||||
---
|
||||
Download the starter kit to get everything you need to
|
||||
[get started with React](/react/docs/getting-started.html). The starter kit includes React, the in-browser JSX transformer, and some simple example apps.
|
||||
[get started with React](/react/docs/getting-started.html). The starter kit includes React and some simple example apps.
|
||||
|
||||
<div class="buttons-unit downloads">
|
||||
<a href="/react/downloads/react-{{site.react_version}}.zip" class="button">
|
||||
@@ -20,48 +20,53 @@ If you're just starting out, make sure to use the development version.
|
||||
|
||||
## Individual Downloads
|
||||
|
||||
#### <a href="https://fb.me/react-{{site.react_version}}.js">React {{site.react_version}} (development)</a>
|
||||
The uncompressed, development version of React core with inline documentation.
|
||||
#### React {{site.react_version}} (development)
|
||||
The uncompressed, development version of [react.js](https://fb.me/react-{{site.react_version}}.js) and [react-dom.js](https://fb.me/react-dom-{{site.react_version}}.js) with inline documentation (you need both files).
|
||||
|
||||
```html
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
```
|
||||
|
||||
#### <a href="https://fb.me/react-{{site.react_version}}.min.js">React {{site.react_version}} (production)</a>
|
||||
The compressed, production version of React core.
|
||||
#### React {{site.react_version}} (production)
|
||||
The compressed, production version of [react.js](https://fb.me/react-{{site.react_version}}.min.js) and [react-dom.js](https://fb.me/react-dom-{{site.react_version}}.min.js) (you need both).
|
||||
|
||||
```html
|
||||
<script src="https://fb.me/react-{{site.react_version}}.min.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.min.js"></script>
|
||||
```
|
||||
|
||||
#### <a href="https://fb.me/react-with-addons-{{site.react_version}}.js">React with Add-Ons {{site.react_version}} (development)</a>
|
||||
The uncompressed, development version of React with [add-ons](/react/docs/addons.html).
|
||||
#### React with Add-Ons {{site.react_version}} (development)
|
||||
The uncompressed, development version of React with [optional add-ons](/react/docs/addons.html).
|
||||
|
||||
```html
|
||||
<script src="https://fb.me/react-with-addons-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
```
|
||||
|
||||
#### <a href="https://fb.me/react-with-addons-{{site.react_version}}.min.js">React with Add-Ons {{site.react_version}} (production)</a>
|
||||
The compressed, production version of React with [add-ons](/react/docs/addons.html).
|
||||
#### React with Add-Ons {{site.react_version}} (production)
|
||||
The compressed, production version of React with [optional add-ons](/react/docs/addons.html).
|
||||
|
||||
```html
|
||||
<script src="https://fb.me/react-with-addons-{{site.react_version}}.min.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.min.js"></script>
|
||||
```
|
||||
|
||||
All scripts are also available via [CDNJS](https://cdnjs.com/libraries/react/).
|
||||
|
||||
## npm
|
||||
|
||||
If you're using an npm-compatible packaging system like browserify or webpack, you can use the `react` package. After installing it using `npm install react` or adding `react` to `package.json`, you can use React:
|
||||
We recommend using React from npm with a bundler like [browserify](http://browserify.org/) or [webpack](https://webpack.github.io/). You can use the `react` and `react-dom` packages. After installing it using `npm install --save react react-dom`, you can use:
|
||||
|
||||
```js
|
||||
var React = require('react-dom');
|
||||
ReactDOM.render(...);
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
ReactDOM.render(<App />, ...);
|
||||
```
|
||||
|
||||
If you'd like to use any [add-ons](/react/docs/addons.html), use `var React = require('react/addons');` instead.
|
||||
Each of the [add-ons](/react/docs/addons.html) lives in its own package.
|
||||
|
||||
**Note:** by default, React will be in development mode. To use React in production mode, set the environment variable `NODE_ENV` to `production`. A minifier that performs dead-code elimination such as [UglifyJS](https://github.com/mishoo/UglifyJS2) is recommended to completely remove the extra code present in development mode.
|
||||
**Note:** by default, React will be in development mode. To use React in production mode, set the environment variable `NODE_ENV` to `production` (using envify or webpack's DefinePlugin). A minifier that performs dead-code elimination such as [UglifyJS](https://github.com/mishoo/UglifyJS2) is recommended to completely remove the extra code present in development mode.
|
||||
|
||||
## Bower
|
||||
|
||||
|
||||
BIN
docs/downloads/react-0.14.0.zip
Normal file
BIN
docs/downloads/react-0.14.0.zip
Normal file
Binary file not shown.
BIN
docs/downloads/react-0.14.1.zip
Normal file
BIN
docs/downloads/react-0.14.1.zip
Normal file
Binary file not shown.
2
docs/js/react-dom.js
vendored
2
docs/js/react-dom.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* ReactDOM v0.14.0-rc1
|
||||
* ReactDOM v0.14.1
|
||||
*
|
||||
* Copyright 2013-2015, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
|
||||
703
docs/js/react.js
vendored
703
docs/js/react.js
vendored
File diff suppressed because it is too large
Load Diff
9266
npm-shrinkwrap.json
generated
Normal file
9266
npm-shrinkwrap.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react-build",
|
||||
"private": true,
|
||||
"version": "0.14.0-rc1",
|
||||
"version": "0.14.2",
|
||||
"devDependencies": {
|
||||
"babel": "^5.8.3",
|
||||
"babel-eslint": "^4.1.3",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "react-addons",
|
||||
"version": "0.14.0-rc1",
|
||||
"version": "0.14.2",
|
||||
"main": "index.js",
|
||||
"license": "BSD-3-Clause",
|
||||
"peerDependencies": {
|
||||
"react": "^0.14.0-rc1"
|
||||
"react": "^0.14.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-dom",
|
||||
"version": "0.14.0-rc1",
|
||||
"version": "0.14.2",
|
||||
"description": "React package for working with the DOM.",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
@@ -15,7 +15,7 @@
|
||||
"url": "https://github.com/facebook/react/issues"
|
||||
},
|
||||
"homepage": "https://github.com/facebook/react/tree/master/npm-react-dom",
|
||||
"dependencies": {
|
||||
"react": "^0.14.0-rc1"
|
||||
"peerDependencies": {
|
||||
"react": "^0.14.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ To use React in production mode, set the environment variable `NODE_ENV` to `pro
|
||||
```js
|
||||
var React = require('react');
|
||||
|
||||
// Addons can be accessed individually from the "addons" directory.
|
||||
var createFragment = require('react/addons/createFragment');
|
||||
var immutabilityHelpers = require('react/addons/update');
|
||||
var CSSTransitionGroup = require('react/addons/CSSTransitionGroup');
|
||||
// Addons are in separate packages:
|
||||
var createFragment = require('react-addons-create-fragment');
|
||||
var immutabilityHelpers = require('react-addons-update');
|
||||
var CSSTransitionGroup = require('react-addons-css-transition-group');
|
||||
```
|
||||
|
||||
For a complete list of addons visit the [addons documentation page](https://facebook.github.io/react/docs/addons.html).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react",
|
||||
"description": "React is a JavaScript library for building user interfaces.",
|
||||
"version": "0.14.0-rc1",
|
||||
"version": "0.14.2",
|
||||
"keywords": [
|
||||
"react"
|
||||
],
|
||||
|
||||
@@ -11,4 +11,4 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = '0.14.0-rc1';
|
||||
module.exports = '0.14.2';
|
||||
|
||||
@@ -27,7 +27,7 @@ function createTransitionTimeoutPropValidator(transitionType) {
|
||||
// If the transition is enabled
|
||||
if (props[enabledPropName]) {
|
||||
// If no timeout duration is provided
|
||||
if (!props[timeoutPropName]) {
|
||||
if (props[timeoutPropName] == null) {
|
||||
return new Error(
|
||||
timeoutPropName + ' wasn\'t supplied to ReactCSSTransitionGroup: ' +
|
||||
'this can cause unreliable animations and won\'t be supported in ' +
|
||||
|
||||
@@ -23,6 +23,7 @@ describe('ReactCSSTransitionGroup', function() {
|
||||
var container;
|
||||
|
||||
beforeEach(function() {
|
||||
require('mock-modules').dumpCache();
|
||||
React = require('React');
|
||||
ReactDOM = require('ReactDOM');
|
||||
ReactCSSTransitionGroup = require('ReactCSSTransitionGroup');
|
||||
@@ -47,6 +48,22 @@ describe('ReactCSSTransitionGroup', function() {
|
||||
expect(console.error.argsForCall.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should not warn if timeouts is zero', function() {
|
||||
ReactDOM.render(
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="yolo"
|
||||
transitionEnter={false}
|
||||
transitionLeave={true}
|
||||
transitionLeaveTimeout={0}
|
||||
>
|
||||
<span key="one" id="one" />
|
||||
</ReactCSSTransitionGroup>,
|
||||
container
|
||||
);
|
||||
|
||||
expect(console.error.argsForCall.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should clean-up silently after the timeout elapses', function() {
|
||||
var a = ReactDOM.render(
|
||||
<ReactCSSTransitionGroup
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
var ReactCurrentOwner = require('ReactCurrentOwner');
|
||||
|
||||
var assign = require('Object.assign');
|
||||
var canDefineProperty = require('canDefineProperty');
|
||||
|
||||
// The Symbol used to tag the ReactElement type. If there is no native Symbol
|
||||
// nor polyfill, then a plain number is used for performance.
|
||||
@@ -28,16 +29,6 @@ var RESERVED_PROPS = {
|
||||
__source: true,
|
||||
};
|
||||
|
||||
var canDefineProperty = false;
|
||||
if (__DEV__) {
|
||||
try {
|
||||
Object.defineProperty({}, 'x', {});
|
||||
canDefineProperty = true;
|
||||
} catch (x) {
|
||||
// IE will fail on defineProperty
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base constructor for all React elements. This is only used to make this
|
||||
* work with a dynamic instanceof check. Nothing should live on this prototype.
|
||||
|
||||
@@ -23,6 +23,7 @@ var ReactPropTypeLocations = require('ReactPropTypeLocations');
|
||||
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
|
||||
var ReactCurrentOwner = require('ReactCurrentOwner');
|
||||
|
||||
var canDefineProperty = require('canDefineProperty');
|
||||
var getIteratorFn = require('getIteratorFn');
|
||||
var invariant = require('invariant');
|
||||
var warning = require('warning');
|
||||
@@ -298,7 +299,7 @@ var ReactElementValidator = {
|
||||
validatedFactory.type = type;
|
||||
|
||||
if (__DEV__) {
|
||||
try {
|
||||
if (canDefineProperty) {
|
||||
Object.defineProperty(
|
||||
validatedFactory,
|
||||
'type',
|
||||
@@ -317,8 +318,6 @@ var ReactElementValidator = {
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (x) {
|
||||
// IE will fail on defineProperty (es5-shim/sham too)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
var ReactNoopUpdateQueue = require('ReactNoopUpdateQueue');
|
||||
|
||||
var canDefineProperty = require('canDefineProperty');
|
||||
var emptyObject = require('emptyObject');
|
||||
var invariant = require('invariant');
|
||||
var warning = require('warning');
|
||||
@@ -129,7 +130,7 @@ if (__DEV__) {
|
||||
],
|
||||
};
|
||||
var defineDeprecationWarning = function(methodName, info) {
|
||||
try {
|
||||
if (canDefineProperty) {
|
||||
Object.defineProperty(ReactComponent.prototype, methodName, {
|
||||
get: function() {
|
||||
warning(
|
||||
@@ -141,8 +142,6 @@ if (__DEV__) {
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
} catch (x) {
|
||||
// IE will fail on defineProperty (es5-shim/sham too)
|
||||
}
|
||||
};
|
||||
for (var fnName in deprecatedAPIs) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"name": "react",
|
||||
"jstest": {
|
||||
"useAutoMock": false
|
||||
}
|
||||
"name": "react-haste",
|
||||
"version": "0.14.2",
|
||||
"license": "BSD-3-Clause"
|
||||
}
|
||||
|
||||
@@ -635,12 +635,17 @@ var ReactMount = {
|
||||
var prevWrappedElement = prevComponent._currentElement;
|
||||
var prevElement = prevWrappedElement.props;
|
||||
if (shouldUpdateReactComponent(prevElement, nextElement)) {
|
||||
return ReactMount._updateRootComponent(
|
||||
var publicInst = prevComponent._renderedComponent.getPublicInstance();
|
||||
var updatedCallback = callback && function() {
|
||||
callback.call(publicInst);
|
||||
};
|
||||
ReactMount._updateRootComponent(
|
||||
prevComponent,
|
||||
nextWrappedElement,
|
||||
container,
|
||||
callback
|
||||
)._renderedComponent.getPublicInstance();
|
||||
updatedCallback
|
||||
);
|
||||
return publicInst;
|
||||
} else {
|
||||
ReactMount.unmountComponentAtNode(container);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user