Compare commits
144 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15a8fc105f | ||
|
|
da0beaf179 | ||
|
|
89ca6df46b | ||
|
|
57a4c1d597 | ||
|
|
56e9ce8c91 | ||
|
|
6a072b3f81 | ||
|
|
5d7f398ca8 | ||
|
|
fe3cfcd3b2 | ||
|
|
6a87954262 | ||
|
|
4ccf18b9a0 | ||
|
|
4a9e52efb4 | ||
|
|
82982f6dab | ||
|
|
a7321487c9 | ||
|
|
3e1a2f18f6 | ||
|
|
c3b7f937b0 | ||
|
|
5bed1f3d3c | ||
|
|
c0993bf1a8 | ||
|
|
19953781e4 | ||
|
|
dad9991a75 | ||
|
|
d824d0d03b | ||
|
|
4c4bfba2c3 | ||
|
|
b17b2ea3f6 | ||
|
|
25fdaf95be | ||
|
|
5f7f9b1552 | ||
|
|
3ff62fa9d1 | ||
|
|
95d310cad2 | ||
|
|
c03a057f9a | ||
|
|
1b2286e933 | ||
|
|
6bde147f3e | ||
|
|
1e065c89c9 | ||
|
|
103074f4cc | ||
|
|
23b1f97aaa | ||
|
|
e01bac801f | ||
|
|
4bba4207ee | ||
|
|
9ce4be4430 | ||
|
|
d68bead611 | ||
|
|
9479256e7e | ||
|
|
9e821ee60a | ||
|
|
c585396f2e | ||
|
|
cd654486f8 | ||
|
|
84e099c3af | ||
|
|
2152045b44 | ||
|
|
200dcdad0a | ||
|
|
5730beca2b | ||
|
|
3888b47da4 | ||
|
|
4226ee589d | ||
|
|
e48343bd03 | ||
|
|
88543cec19 | ||
|
|
741124548d | ||
|
|
05acd8ed35 | ||
|
|
8fb9daa5ed | ||
|
|
2f77642b9f | ||
|
|
49617c3be7 | ||
|
|
3285d83440 | ||
|
|
decfbdf1f5 | ||
|
|
79732f04bf | ||
|
|
b797075c63 | ||
|
|
44f1a9a262 | ||
|
|
4ecc10880e | ||
|
|
5189deb5ee | ||
|
|
9adfb08868 | ||
|
|
f5dd3e7cf6 | ||
|
|
da3c9527c5 | ||
|
|
2a1dc07046 | ||
|
|
8c27faab7a | ||
|
|
9e380c2679 | ||
|
|
7594b977d6 | ||
|
|
a808423626 | ||
|
|
ecd2da90e5 | ||
|
|
60afae7ca5 | ||
|
|
381fe0b3e6 | ||
|
|
2f21dc6f76 | ||
|
|
e45c534f6d | ||
|
|
76aa60db91 | ||
|
|
4206fd1dce | ||
|
|
d590910f6d | ||
|
|
cf17f3291f | ||
|
|
5879799f8e | ||
|
|
80cadc6f66 | ||
|
|
44e90c040d | ||
|
|
d5bf8c553f | ||
|
|
e278ce4445 | ||
|
|
06cad05d49 | ||
|
|
f305deb065 | ||
|
|
9c091afe74 | ||
|
|
fb6b3b05f4 | ||
|
|
575cf6a82e | ||
|
|
d6a0a083e4 | ||
|
|
e7b178390d | ||
|
|
a9732ba548 | ||
|
|
05269bf16b | ||
|
|
093a97c54b | ||
|
|
0d5d0b2688 | ||
|
|
c8398491d8 | ||
|
|
149613d065 | ||
|
|
0516e74473 | ||
|
|
3f355d99c5 | ||
|
|
a29b4938a8 | ||
|
|
142059d294 | ||
|
|
d2dde00940 | ||
|
|
d9bf86e83a | ||
|
|
527d7b154b | ||
|
|
f8777eea9e | ||
|
|
6dd8427c20 | ||
|
|
33cae8c9b1 | ||
|
|
881d023c0e | ||
|
|
926378cacb | ||
|
|
343109e248 | ||
|
|
5fd421c996 | ||
|
|
1f1a127891 | ||
|
|
7bb2119733 | ||
|
|
a4ad2b4e54 | ||
|
|
050b8f1875 | ||
|
|
821104185e | ||
|
|
dc5411c795 | ||
|
|
a1decaf2a5 | ||
|
|
b6dc8681bb | ||
|
|
4588820073 | ||
|
|
852a63fe23 | ||
|
|
617cfdd434 | ||
|
|
85c09e5507 | ||
|
|
235b914797 | ||
|
|
9ed0fdb850 | ||
|
|
e2e04fdbc3 | ||
|
|
1f41a53d1e | ||
|
|
3ef0838567 | ||
|
|
319a266941 | ||
|
|
d5f312866b | ||
|
|
2c5dadb0c5 | ||
|
|
0f7fad10d6 | ||
|
|
da7b9043a4 | ||
|
|
cc92028f11 | ||
|
|
969014c832 | ||
|
|
b335180686 | ||
|
|
33717bc425 | ||
|
|
9921659616 | ||
|
|
f974581a6a | ||
|
|
ef20f03429 | ||
|
|
1eed5b0e10 | ||
|
|
934d5b642e | ||
|
|
40e4655a5e | ||
|
|
789a9b70cb | ||
|
|
3a793ba27b | ||
|
|
3f2f763dea |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -24,3 +24,4 @@ chrome-user-data
|
||||
*.sublime-workspace
|
||||
.idea
|
||||
*.iml
|
||||
.vscode
|
||||
|
||||
40
CHANGELOG.md
40
CHANGELOG.md
@@ -1,3 +1,43 @@
|
||||
## 0.14.8 (March 29, 2016)
|
||||
|
||||
### React
|
||||
- Fixed memory leak when rendering on the server
|
||||
|
||||
## 0.14.7 (January 28, 2016)
|
||||
|
||||
### React
|
||||
- Fixed bug with `<option>` tags when using `dangerouslySetInnerHTML`
|
||||
- Fixed memory leak in synthetic event system
|
||||
|
||||
### React TestUtils Add-on
|
||||
- Fixed bug with calling `setState` in `componentWillMount` when using shallow rendering
|
||||
|
||||
|
||||
## 0.14.6 (January 6, 2016)
|
||||
|
||||
### React
|
||||
- Updated `fbjs` dependency to pick up change affecting handling of undefined document.
|
||||
|
||||
|
||||
## 0.14.5 (December 29, 2015)
|
||||
|
||||
### React
|
||||
- More minor internal changes for better compatibility with React Native
|
||||
|
||||
|
||||
## 0.14.4 (December 29, 2015)
|
||||
|
||||
### React
|
||||
- Minor internal changes for better compatibility with React Native
|
||||
|
||||
### React DOM
|
||||
- The `autoCapitalize` and `autoCorrect` props are now set as attributes in the DOM instead of properties to improve cross-browser compatibility
|
||||
- Fixed bug with controlled `<select>` elements not handling updates properly
|
||||
|
||||
### React Perf Add-on
|
||||
- Some DOM operation names have been updated for clarity in the output of `.printDOM()`
|
||||
|
||||
|
||||
## 0.14.3 (November 18, 2015)
|
||||
|
||||
### React DOM
|
||||
|
||||
@@ -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.14.3.js"></script>
|
||||
<script src="https://fb.me/react-0.14.8.js"></script>
|
||||
<!-- The ReactDOM Library -->
|
||||
<script src="https://fb.me/react-dom-0.14.3.js"></script>
|
||||
<script src="https://fb.me/react-dom-0.14.8.js"></script>
|
||||
```
|
||||
|
||||
We've also built a [starter kit](https://facebook.github.io/react/downloads/react-0.14.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.8.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:
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ require('yaml')
|
||||
desc "generate js from jsx"
|
||||
task :js do
|
||||
system "cp ../node_modules/babel/node_modules/babel-core/browser.min.js ./js/babel-browser.min.js"
|
||||
system "../node_modules/.bin/babel _js --out-dir=js"
|
||||
system "../node_modules/babel/bin/babel.js _js --out-dir=js"
|
||||
end
|
||||
|
||||
desc "watch js"
|
||||
@@ -24,6 +24,25 @@ task :update_version do
|
||||
end
|
||||
end
|
||||
|
||||
desc "update SRI hashes"
|
||||
task :update_hashes do
|
||||
map = {
|
||||
'react.js' => 'dev',
|
||||
'react.min.js' => 'prod',
|
||||
'react-with-addons.js' => 'addons_dev',
|
||||
'react-with-addons.min.js' => 'addons_prod',
|
||||
'react-dom.js' => 'dom_dev',
|
||||
'react-dom.min.js' => 'dom_prod',
|
||||
'react-dom-server.js' => 'dom_server_dev',
|
||||
'react-dom-server.min.js' => 'dom_server_prod'
|
||||
}
|
||||
site_config = YAML.load_file('_config.yml')
|
||||
map.each do |file, key|
|
||||
site_config['react_hashes'][key] = `openssl dgst -sha384 -binary ../../react-bower/#{file} | openssl base64 -A`
|
||||
end
|
||||
File.open('_config.yml', 'w+') { |f| f.write(site_config.to_yaml) }
|
||||
end
|
||||
|
||||
desc "update acknowledgements list"
|
||||
task :update_acknowledgements do
|
||||
authors = File.readlines('../AUTHORS').map {|author| author.gsub(/ <.*\n/,'')}
|
||||
|
||||
@@ -36,4 +36,13 @@ sass:
|
||||
sass_dir: _css
|
||||
gems:
|
||||
- jekyll-redirect-from
|
||||
react_version: 0.14.2
|
||||
react_version: 0.14.7
|
||||
react_hashes:
|
||||
dev: xQae1pUPdAKUe0u0KUTNt09zzdwheX4VSUsV8vatqM+t6X7rta01qOzessL808ox
|
||||
prod: zTm/dblzLXQNp3CgY+hfaC/WJ6h4XtNrePh2CW2+rO9GPuNiPb9jmthvAL+oI/dQ
|
||||
addons_dev: I5TF2q2QDmB31aN5lcClArdUo+WJH/Yi3hcH3PBVXFe5DYtYCFh7Jx/dmpba12zn
|
||||
addons_prod: KPHTQfiYMhtsIRbZcY4ri1lBYZQbj4ePsSdzODR2Bu5L5ts3APVyqwKPBThO5Hgc
|
||||
dom_dev: A1t0GCrR06cTHvMjaxeSE8XOiz6j7NvWdmxhN/9z748wEvJTVk13Rr8gMzTUnd8G
|
||||
dom_prod: ntqCsHbLdMxT352UbhPbT7fqjE8xi4jLmQYQa8mYR+ylAapbXRfdsDweueDObf7m
|
||||
dom_server_dev: 3I5+eGB/ILYa6pQQX+rM9O0SyDltamM40RiZ5JvIijSYEfVGZU0vY4Iwx9a1eYyD
|
||||
dom_server_prod: Kt9dEqXzv00orFPW2o3H+kxQtSiNO8EqXsXJT3i99rCcp74N/Km98V0kUxAzy44k
|
||||
|
||||
@@ -13,6 +13,9 @@ Daniel15:
|
||||
fisherwebdev:
|
||||
name: Bill Fisher
|
||||
url: https://twitter.com/fisherwebdev
|
||||
gaearon:
|
||||
name: Dan Abramov
|
||||
url: https://twitter.com/dan_abramov
|
||||
jaredly:
|
||||
name: Jared Forsyth
|
||||
url: https://twitter.com/jaredforsyth
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
title: Videos
|
||||
- id: complementary-tools
|
||||
title: Complementary Tools
|
||||
href: https://github.com/facebook/react/wiki/Complementary-Tools
|
||||
- id: examples
|
||||
title: Examples
|
||||
href: https://github.com/facebook/react/wiki/Examples
|
||||
- title: Guides
|
||||
items:
|
||||
- id: why-react
|
||||
@@ -65,6 +67,8 @@
|
||||
title: PureRenderMixin
|
||||
- id: perf
|
||||
title: Performance Tools
|
||||
- id: shallow-compare
|
||||
title: Shallow Compare
|
||||
- id: advanced-performance
|
||||
title: Advanced Performance
|
||||
- id: context
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
var TODO_COMPONENT = `
|
||||
var TodoList = React.createClass({
|
||||
render: function() {
|
||||
var createItem = function(itemText, index) {
|
||||
return <li key={index + itemText}>{itemText}</li>;
|
||||
var createItem = function(item) {
|
||||
return <li key={item.id}>{item.text}</li>;
|
||||
};
|
||||
return <ul>{this.props.items.map(createItem)}</ul>;
|
||||
}
|
||||
@@ -16,7 +16,7 @@ var TodoApp = React.createClass({
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var nextItems = this.state.items.concat([this.state.text]);
|
||||
var nextItems = this.state.items.concat([{text: this.state.text, id: Date.now()}]);
|
||||
var nextText = '';
|
||||
this.setState({items: nextItems, text: nextText});
|
||||
},
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<link rel="shortcut icon" href="/react/favicon.ico">
|
||||
<link rel="alternate" type="application/rss+xml" title="{{ site.name }}" href="{{ site.url }}{{ site.baseurl }}/feed.xml">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css" />
|
||||
<link rel="stylesheet" href="/react/css/syntax.css">
|
||||
<link rel="stylesheet" href="/react/css/codemirror.css">
|
||||
<link rel="stylesheet" href="/react/css/react.css">
|
||||
@@ -28,6 +29,7 @@
|
||||
<script src="/react/js/es5-shim.min.js"></script>
|
||||
<script src="/react/js/es5-sham.min.js"></script>
|
||||
<![endif]-->
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script>
|
||||
<script src="/react/js/codemirror.js"></script>
|
||||
<script src="/react/js/javascript.js"></script>
|
||||
<script src="/react/js/react.js"></script>
|
||||
@@ -50,11 +52,14 @@
|
||||
<li><a href="/react/support.html"{% if page.id == 'support' %} class="active"{% endif %}>Support</a></li>
|
||||
<li><a href="/react/downloads.html"{% if page.id == 'downloads' %} class="active"{% endif %}>Download</a></li>
|
||||
<li><a href="/react/blog/"{% if page.sectionid == 'blog' %} class="active"{% endif %}>Blog</a></li>
|
||||
<li>
|
||||
<input id="algolia-doc-search" type="text" placeholder="Search docs..." />
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav-site nav-site-external">
|
||||
<li><a href="https://github.com/facebook/react">GitHub</a>
|
||||
<li><a href="https://facebook.github.io/react-native/">React Native</a>
|
||||
<li><a href="https://github.com/facebook/react">GitHub</a></li>
|
||||
<li><a href="https://facebook.github.io/react-native/">React Native</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -107,6 +112,12 @@
|
||||
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=623268441017527";
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}(document, 'script', 'facebook-jssdk'));
|
||||
|
||||
docsearch({
|
||||
apiKey: '36221914cce388c46d0420343e0bb32e',
|
||||
indexName: 'react',
|
||||
inputSelector: '#algolia-doc-search'
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
8
docs/_layouts/redirect.html
Normal file
8
docs/_layouts/redirect.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Redirecting...</title>
|
||||
<link rel=canonical href="{{ page.dest_url }}">
|
||||
<meta http-equiv=refresh content="0; url={{ page.dest_url }}">
|
||||
<h1>Redirecting...</h1>
|
||||
<a href="{{ page.dest_url }}">Click here if you are not redirected.</a>
|
||||
<script>location="{{ page.dest_url }}"</script>
|
||||
@@ -4,7 +4,14 @@ module Jekyll
|
||||
pageID = @context.registers[:page]["id"]
|
||||
itemID = item["id"]
|
||||
href = item["href"] || "/react/docs/#{itemID}.html"
|
||||
className = pageID == itemID ? ' class="active"' : ''
|
||||
classes = []
|
||||
if pageID == itemID
|
||||
classes.push("active")
|
||||
end
|
||||
if item["href"]
|
||||
classes.push("external")
|
||||
end
|
||||
className = classes.size > 0 ? " class=\"#{classes.join(' ')}\"" : ""
|
||||
|
||||
return "<a href=\"#{href}\"#{className}>#{item["title"]}</a>"
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ While this is not going to work for all the attributes since they are camelCased
|
||||
|
||||
## Remarkable React
|
||||
|
||||
[Stoyan Stefanov](http://www.phpied.com/) gave a talk at [BrazilJS](http://braziljs.com.br/) about React and wrote an article with the content of the presentation. He goes through the difficulties of writting _active apps_ using the DOM API and shows how React handles it.
|
||||
[Stoyan Stefanov](http://www.phpied.com/) gave a talk at [BrazilJS](http://braziljs.com.br/) about React and wrote an article with the content of the presentation. He goes through the difficulties of writing _active apps_ using the DOM API and shows how React handles it.
|
||||
|
||||
> So how does exactly React deal with it internally? Two crazy ideas - virtual DOM and synthetic events.
|
||||
>
|
||||
|
||||
@@ -54,7 +54,7 @@ It's great to see the React community expand internationally. [This site](http:/
|
||||
|
||||
### Egghead.io video tutorials
|
||||
|
||||
Joe Maddalone ([@joemaddalone](https://twitter.com/joemaddalone)) of [egghead.io](https://egghead.io/) created a series of React video tutorials, such as [this](http://www.youtube-nocookie.com/watch?v=rFvZydtmsxM&feature=youtu.be&a) introduction to React Components. [[part 1](http://www.youtube-nocookie.com/watch?v=rFvZydtmsxM&feature=youtu.be&a)], [[part 2](http://www.youtube-nocookie.com/watch?v=5yvFLrt7N8M)]
|
||||
Joe Maddalone ([@joemaddalone](https://twitter.com/joemaddalone)) of [egghead.io](https://egghead.io/) created a series of React video tutorials, such as [this](http://www.youtube-nocookie.com/v/rFvZydtmsxM) introduction to React Components. [[part 1](http://www.youtube-nocookie.com/v/rFvZydtmsxM)], [[part 2](http://www.youtube-nocookie.com/v/5yvFLrt7N8M)]
|
||||
|
||||
### "React: Finally, a great server/client web stack"
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ We have wanted to do this since before we even open sourced React. No more `/**
|
||||
|
||||
The React specific JSX transform no longer transforms to function calls. Instead we use `React.createElement` and pass it arguments. This allows us to make optimizations and better support React as a compile target for things like Om. Read more in the [React Elements introduction](/react/blog/2014/10/14/introducting-react-elements.html).
|
||||
|
||||
The result of this change is that we will no longer support arbitrary function calls. We understand that the ability to do was was a convenient shortcut for many people but we believe the gains will be worth it.
|
||||
The result of this change is that we will no longer support arbitrary function calls. We understand that the ability to do was a convenient shortcut for many people but we believe the gains will be worth it.
|
||||
|
||||
|
||||
### JSX Lower-case Convention
|
||||
|
||||
@@ -17,7 +17,7 @@ stick with the originally planned format and venue on Facebook's campus.
|
||||
|
||||
Unfortunately, this means that we can only accept a small number of the awesome
|
||||
conference talk proposals. In order to make sure attendees get a fair shot at
|
||||
registering, we're going to to sell tickets in three separate first-come,
|
||||
registering, we're going to sell tickets in three separate first-come,
|
||||
first-serve phases. **Tickets will cost $200 regardless of which phase they are
|
||||
purchased from and all proceeds will go to charity**.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ layout: post
|
||||
author: steveluscher
|
||||
---
|
||||
|
||||
It was a privilege to welcome the React community to Facebook HQ on January 28–29 for the first-ever React.js Conf, and a pleasure to be be able to unveil three new technologies that we've been using internally at Facebook for some time: GraphQL, Relay, and React Native.
|
||||
It was a privilege to welcome the React community to Facebook HQ on January 28–29 for the first-ever React.js Conf, and a pleasure to be able to unveil three new technologies that we've been using internally at Facebook for some time: GraphQL, Relay, and React Native.
|
||||
|
||||
## The talks
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Building The Facebook News Feed With Relay"
|
||||
author: josephsavona
|
||||
---
|
||||
|
||||
At React.js Conf in January we gave a preview of Relay, a new framework for building data-driven applications in React. In this post, we'll describe the process of creating a Relay application. This post assumes some familiarity with the concepts of Relay and GraphQL, so if you haven't already we recommend reading [our introductory blog post](/react/blog/2015/02/20/introducing-relay-and-graphql.html) or watching [the conference talk](https://www.youtube-nocookie.com/watch?v=9sc8Pyc51uU).
|
||||
At React.js Conf in January we gave a preview of Relay, a new framework for building data-driven applications in React. In this post, we'll describe the process of creating a Relay application. This post assumes some familiarity with the concepts of Relay and GraphQL, so if you haven't already we recommend reading [our introductory blog post](/react/blog/2015/02/20/introducing-relay-and-graphql.html) or watching [the conference talk](https://www.youtube-nocookie.com/v/9sc8Pyc51uU).
|
||||
|
||||
We're working hard to prepare GraphQL and Relay for public release. In the meantime, we'll continue to provide information about what you can expect.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "React v0.14.3"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
It's time for another installment of React patch releases! We didn't break anything in v0.14.2 but we do have a couple of other bugs we're fixing. The biggest change in this release is actually an addition of a new built file. We heard from a number of people that they still need the ability to use React to render to a string on the client. While the use cases are not common and there are other ways to achieve this, we decided that it's still valuable to support. So we're now building `react-dom-server.js`, which will be shipped to Bower and in the `dist/` directory of the `react-dom` package on npm. This file works the same was as `react-dom.js` and therefore requires that the primary React build has already been included on the page.
|
||||
It's time for another installment of React patch releases! We didn't break anything in v0.14.2 but we do have a couple of other bugs we're fixing. The biggest change in this release is actually an addition of a new built file. We heard from a number of people that they still need the ability to use React to render to a string on the client. While the use cases are not common and there are other ways to achieve this, we decided that it's still valuable to support. So we're now building `react-dom-server.js`, which will be shipped to Bower and in the `dist/` directory of the `react-dom` package on npm. This file works the same way as `react-dom.js` and therefore requires that the primary React build has already been included on the page.
|
||||
|
||||
The release is now available for download:
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: React.js Conf 2016 Diversity Scholarship
|
||||
author: zpao
|
||||
---
|
||||
|
||||
I am thrilled to announced that we will be organizing another diversity scholarship program for the upcoming React.js Conf! The tech industry is suffering from a lack of diversity, but it's important to us that we have a thriving community that is made up of people with a variety of experiences and viewpoints.
|
||||
|
||||
When we ran this program last year, we had *over 200* people apply for only 10 tickets. There were so many people that we wanted to bring in but we couldn't. The results were still awesome, and we had bright individuals from around the world attending who would have otherwise been unable to. These attendees took part in discussions at the conference and brought perspectives that we might not have otherwise seen there.
|
||||
|
||||
This year we're excited to bring back the scholarship, but we've set aside **40 tickets** because we really believe that it's important to do our best to make sure we have an even more diverse audience.
|
||||
|
||||
This is something I'm personally really excited to be a part of. I know the rest of the team is as well. We're really proud to have everyone at Facebook providing support and funding for this.
|
||||
|
||||
The details of the scholarship are provided below (or you can [go directly to the application](http://goo.gl/forms/PEmKj8oUp4)). I encourage you to apply! If you don't feel like you are eligible yourself, you can still help – send this along to friends, family, coworkers, acquaintances, or anybody who might be interested. And even if you haven't spoken before, please consider [submitting a proposal for a talk](http://conf.reactjs.com/) (either 30 minutes or just 5 minutes) - we're hoping to have a very diverse group of speakers in addition to attendees.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
Facebook is excited to announce that we are now accepting applications for the React.js Conf Diversity Scholarship!
|
||||
|
||||
Beginning today, those studying or working in computer science or a related field can apply for a partial scholarship to attend the React.js Conf in San Francisco, CA on February 22 & 23, 2016.
|
||||
|
||||
React opens a world of new possibilities such as server-side rendering, real-time updates, different rendering targets like SVG and canvas. React Native makes is easy to use the same concepts and technologies to build native mobile experiences on iOS and Android. Join us at React.js Conf to shape the future of client-side applications! For more information about the React.js conference, please see [the website](http://conf.reactjs.com/).
|
||||
|
||||
At Facebook, we believe that anyone anywhere can make a positive impact by developing products to make the world more open and connected to the people and things they care about. Given the current realities of the tech industry and the lack of representation of communities we seek to serve, applicants currently under-represented in Computer Science and related fields are strongly encouraged to apply. Facebook will make determinations on scholarship recipients in its sole discretion. Facebook complies with all equal opportunity laws.
|
||||
|
||||
To apply for the scholarship, please visit the application page: **<http://goo.gl/forms/PEmKj8oUp4>**
|
||||
|
||||
## Award Includes
|
||||
|
||||
* Paid registration fee for the React.js Conf Feburary 22 & 23 in downtown San Francisco, CA
|
||||
* Paid lodging expenses for February 21, 22, 23
|
||||
|
||||
## Important Dates
|
||||
|
||||
* Sunday December 13th 2015 - 11:59 PST: Applications for the React.js Conf Scholarship must be submitted in full
|
||||
* Wednesday, December 16th, 2015: Award recipients will be notified by email of their acceptance
|
||||
* Monday & Tuesday, February 22 & 23, 2016: React.js Conf
|
||||
|
||||
## Eligibility
|
||||
|
||||
* Must currently be studying or working in Computer Science or a related field
|
||||
* International applicants are welcome, but you will be responsible for securing your own visa to attend the conference
|
||||
* You must be able to provide your own transportation to San Francisco
|
||||
* You must be available to attend the full duration of React.js Conf on February 22 & 23 in San Francisco, CA
|
||||
80
docs/_posts/2015-12-16-ismounted-antipattern.md
Normal file
80
docs/_posts/2015-12-16-ismounted-antipattern.md
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: "isMounted is an Antipattern"
|
||||
author: jimfb
|
||||
---
|
||||
|
||||
As we move closer to officially deprecating isMounted, it's worth understanding why the function is an antipattern, and how to write code without the isMounted function.
|
||||
|
||||
The primary use case for `isMounted()` is to avoid calling `setState()` after a component has unmounted, because calling `setState()` after a component has unmounted will emit a warning. The “setState warning” exists to help you catch bugs, because calling `setState()` on an unmounted component is an indication that your app/component has somehow failed to clean up properly. Specifically, calling `setState()` in an unmounted component means that your app is still holding a reference to the component after the component has been unmounted - which often indicates a memory leak!
|
||||
|
||||
To avoid the error message, people often add lines like this:
|
||||
|
||||
```js
|
||||
if(this.isMounted()) { // This is bad.
|
||||
this.setState({...});
|
||||
}
|
||||
```
|
||||
|
||||
Checking `isMounted` before calling `setState()` does eliminate the warning, but it also defeats the purpose of the warning, since now you will never get the warning (even when you should!)
|
||||
|
||||
Other uses of `isMounted()` are similarly erroneous; using `isMounted()` is a code smell because the only reason you would check is because you think you might be holding a reference after the component has unmounted.
|
||||
|
||||
An easy migration strategy for anyone upgrading their code to avoid `isMounted()` is to track the mounted status yourself. Just set a `_isMounted` property to true in `componentDidMount` and set it to false in `componentWillUnmount`, and use this variable to check your component's status.
|
||||
|
||||
An optimal solution would be to find places where `setState()` might be called after a component has unmounted, and fix them. Such situations most commonly occur due to callbacks, when a component is waiting for some data and gets unmounted before the data arrives. Ideally, any callbacks should be canceled in `componentWillUnmount`, prior to unmounting.
|
||||
|
||||
For instance, if you are using a Flux store in your component, you must unsubscribe in `componentWillUnmount`:
|
||||
|
||||
```javascript{9}
|
||||
class MyComponent extends React.Component {
|
||||
componentDidMount() {
|
||||
mydatastore.subscribe(this);
|
||||
}
|
||||
render() {
|
||||
...
|
||||
}
|
||||
componentWillUnmount() {
|
||||
mydatastore.unsubscribe(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you use ES6 promises, you may need to wrap your promise in order to make it cancelable.
|
||||
|
||||
```js
|
||||
const cancelablePromise = makeCancelable(
|
||||
new Promise(r => component.setState({...}}))
|
||||
);
|
||||
|
||||
cancelablePromise
|
||||
.promise
|
||||
.then(() => console.log('resolved'))
|
||||
.catch((reason) => console.log('isCanceled', reason.isCanceled));
|
||||
|
||||
cancelablePromise.cancel(); // Cancel the promise
|
||||
```
|
||||
|
||||
Where `makeCancelable` is [defined by @istarkov](https://github.com/facebook/react/issues/5465#issuecomment-157888325) as:
|
||||
|
||||
```js
|
||||
const makeCancelable = (promise) => {
|
||||
let hasCanceled_ = false;
|
||||
|
||||
const wrappedPromise = new Promise((resolve, reject) => {
|
||||
promise.then((val) =>
|
||||
hasCanceled_ ? reject({isCanceled: true}) : resolve(val)
|
||||
);
|
||||
promise.catch((error) =>
|
||||
hasCanceled_ ? reject({isCanceled: true}) : reject(error)
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
promise: wrappedPromise,
|
||||
cancel() {
|
||||
hasCanceled_ = true;
|
||||
},
|
||||
};
|
||||
};
|
||||
```
|
||||
As an added bonus for getting your code cleaned up early, getting rid of `isMounted()` makes it one step easier for you to upgrade to ES6 classes, where using `isMounted()` is already prohibited. Happy coding!
|
||||
@@ -0,0 +1,383 @@
|
||||
---
|
||||
title: "React Components, Elements, and Instances"
|
||||
author: gaearon
|
||||
---
|
||||
|
||||
The difference between **components, their instances, and elements** confuses many React beginners. Why are there three different terms to refer to something that is painted on screen?
|
||||
|
||||
## Managing the Instances
|
||||
|
||||
If you’re new to React, you probably only worked with component classes and instances before. For example, you may declare a `Button` *component* by creating a class. When the app is running, you may have several *instances* of this component on screen, each with its own properties and local state. This is the traditional object-oriented UI programming. Why introduce *elements*?
|
||||
|
||||
In this traditional UI model, it is up to you to take care of creating and destroying child component instances. If a `Form` component wants to render a `Button` component, it needs to create its instance, and manually keep it up to date with any new information.
|
||||
|
||||
```js
|
||||
class Form extends TraditionalObjectOrientedView {
|
||||
render() {
|
||||
// Read some data passed to the view
|
||||
const { isSubmitted, buttonText } = this.attrs;
|
||||
|
||||
if (!isSubmitted && !this.button) {
|
||||
// Form is not yet submitted. Create the button!
|
||||
this.button = new Button({
|
||||
children: buttonText,
|
||||
color: 'blue'
|
||||
});
|
||||
this.el.appendChild(this.button.el);
|
||||
}
|
||||
|
||||
if (this.button) {
|
||||
// The button is visible. Update its text!
|
||||
this.button.attrs.children = buttonText;
|
||||
this.button.render();
|
||||
}
|
||||
|
||||
if (isSubmitted && this.button) {
|
||||
// Form was submitted. Destroy the button!
|
||||
this.el.removeChild(this.button.el);
|
||||
this.button.destroy();
|
||||
}
|
||||
|
||||
if (isSubmitted && !this.message) {
|
||||
// Form was submitted. Show the success message!
|
||||
this.message = new Message({ text: 'Success!' });
|
||||
this.el.appendChild(this.message.el);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is pseudocode, but it is more or less what you end up with when you write composite UI code that behaves consistently in an object-oriented way using a library like Backbone.
|
||||
|
||||
Each component instance has to keep references to its DOM node and to the instances of the children components, and create, update, and destroy them when the time is right. The lines of code grow as the square of the number of possible states of the component, and the parents have direct access to their children component instances, making it hard to decouple them in the future.
|
||||
|
||||
So how is React different?
|
||||
|
||||
## Elements Describe the Tree
|
||||
|
||||
In React, this is where the *elements* come to rescue. **An element is a plain object *describing* a component instance or DOM node and its desired properties.** It contains only information about the component type (for example, a `Button`), its properties (for example, its `color`), and any child elements inside it.
|
||||
|
||||
An element is not an actual instance. Rather, it is a way to tell React what you *want* to see on the screen. You can’t call any methods on the element. It’s just an immutable description object with two fields: `type: (string | ReactClass)` and `props: Object`[^1].
|
||||
|
||||
### DOM Elements
|
||||
|
||||
When an element’s `type` is a string, it represents a DOM node with that tag name, and `props` correspond to its attributes. This is what React will render. For example:
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-blue',
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: 'OK!'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This element is just a way to represent the following HTML as a plain object:
|
||||
|
||||
```html
|
||||
<button class='button button-blue'>
|
||||
<b>
|
||||
OK!
|
||||
</b>
|
||||
</button>
|
||||
```
|
||||
|
||||
Note how elements can be nested. By convention, when we want to create an element tree, we specify one or more child elements as the `children` prop of their containing element.
|
||||
|
||||
What’s important is that both child and parent elements are *just descriptions and not the actual instances*. They don’t refer to anything on the screen when you create them. You can create them and throw them away, and it won’t matter much.
|
||||
|
||||
React elements are easy to traverse, don’t need to be parsed, and of course they are much lighter than the actual DOM elements—they’re just objects!
|
||||
|
||||
### Component Elements
|
||||
|
||||
However, the `type` of an element can also be a function or a class corresponding to a React component:
|
||||
|
||||
```js
|
||||
{
|
||||
type: Button,
|
||||
props: {
|
||||
color: 'blue',
|
||||
children: 'OK!'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is the core idea of React.
|
||||
|
||||
**An element describing a component is also an element, just like an element describing the DOM node. They can be nested and mixed with each other.**
|
||||
|
||||
This feature lets you define a `DangerButton` component as a `Button` with a specific `color` property value without worrying about whether `Button` renders to a DOM `<button>`, a `<div>`, or something else entirely:
|
||||
|
||||
```js
|
||||
const DangerButton = ({ children }) => ({
|
||||
type: Button,
|
||||
props: {
|
||||
color: 'red',
|
||||
children: children
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
You can mix and match DOM and component elements in a single element tree:
|
||||
|
||||
```js
|
||||
const DeleteAccount = () => ({
|
||||
type: 'div',
|
||||
props: {
|
||||
children: [{
|
||||
type: 'p',
|
||||
props: {
|
||||
children: 'Are you sure?'
|
||||
}
|
||||
}, {
|
||||
type: DangerButton,
|
||||
props: {
|
||||
children: 'Yep'
|
||||
}
|
||||
}, {
|
||||
type: Button,
|
||||
props: {
|
||||
color: 'blue',
|
||||
children: 'Cancel'
|
||||
}
|
||||
}]
|
||||
});
|
||||
```
|
||||
|
||||
Or, if you prefer JSX:
|
||||
|
||||
```js
|
||||
const DeleteAccount = () => (
|
||||
<div>
|
||||
<p>Are you sure?</p>
|
||||
<DangerButton>Yep</DangerButton>
|
||||
<Button color='blue'>Cancel</Button>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
This mix and matching helps keep components decoupled from each other, as they can express both *is-a* and *has-a* relationships exclusively through composition:
|
||||
|
||||
* `Button` is a DOM `<button>` with specific properties.
|
||||
* `DangerButton` is a `Button` with specific properties.
|
||||
* `DeleteAccount` contains a `Button` and a `DangerButton` inside a `<div>`.
|
||||
|
||||
### Components Encapsulate Element Trees
|
||||
|
||||
When React sees an element with a function or class `type`, it knows to ask *that* component what element it renders to, given the corresponding `props`.
|
||||
|
||||
When it sees this element:
|
||||
|
||||
```js
|
||||
{
|
||||
type: Button,
|
||||
props: {
|
||||
color: 'blue',
|
||||
children: 'OK!'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
React will ask `Button` what it renders to. The `Button` will return this element:
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-blue',
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: 'OK!'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
React will repeat this process until it knows the underlying DOM tag elements for every component on the page.
|
||||
|
||||
React is like a child asking “what is Y” for every “X is Y” you explain to them until they figure out every little thing in the world.
|
||||
|
||||
Remember the `Form` example above? It can be written in React as follows[^1]:
|
||||
|
||||
```js
|
||||
const Form = ({ isSubmitted, buttonText }) => {
|
||||
if (isSubmitted) {
|
||||
// Form submitted! Return a message element.
|
||||
return {
|
||||
type: Message,
|
||||
props: {
|
||||
text: 'Success!'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Form is still visible! Return a button element.
|
||||
return {
|
||||
type: Button,
|
||||
props: {
|
||||
children: buttonText,
|
||||
color: 'blue'
|
||||
}
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
That’s it! For a React component, props are the input, and an element tree is the output.
|
||||
|
||||
**The returned element tree can contain both elements describing DOM nodes, and elements describing other components. This lets you compose independent parts of UI without relying on their internal DOM structure.**
|
||||
|
||||
We let React create, update, and destroy instances. We *describe* them with elements we return from the components, and React takes care of managing the instances.
|
||||
|
||||
### Components Can Be Classes or Functions
|
||||
|
||||
In the code above, `Form`, `Message`, and `Button` are React components. They can either be written as functions, like above, or as classes descending from `React.Component`. These three ways to declare a component are mostly equivalent:
|
||||
|
||||
```js
|
||||
// 1) As a function of props
|
||||
const Button = ({ children, color }) => ({
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-' + color,
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: children
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 2) Using the React.createClass() factory
|
||||
const Button = React.createClass({
|
||||
render() {
|
||||
const { children, color } = this.props;
|
||||
return {
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-' + color,
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: children
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// 3) As an ES6 class descending from React.Component
|
||||
class Button extends React.Component {
|
||||
render() {
|
||||
const { children, color } = this.props;
|
||||
return {
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-' + color,
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: children
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When a component is defined as a class, it is a little bit more powerful than a functional component. It can store some local state and perform custom logic when the corresponding DOM node is created or destroyed.
|
||||
|
||||
A functional component is less powerful but is simpler, and acts like a class component with just a single `render()` method. Unless you need features available only in a class, we encourage you to use functional components instead.
|
||||
|
||||
**However, whether functions or classes, fundamentally they are all components to React. They take the props as their input, and return the elements as their output.**
|
||||
|
||||
### Top-Down Reconciliation
|
||||
|
||||
When you call:
|
||||
|
||||
```js
|
||||
ReactDOM.render({
|
||||
type: Form,
|
||||
props: {
|
||||
isSubmitted: false,
|
||||
buttonText: 'OK!'
|
||||
}
|
||||
}, document.getElementById('root'));
|
||||
```
|
||||
|
||||
React will ask the `Form` component what element tree it returns, given those `props`. It will gradually “refine” its understanding of your component tree in terms of simpler primitives:
|
||||
|
||||
```js
|
||||
// React: You told me this...
|
||||
{
|
||||
type: Form,
|
||||
props: {
|
||||
isSubmitted: false,
|
||||
buttonText: 'OK!'
|
||||
}
|
||||
}
|
||||
|
||||
// React: ...And Form told me this...
|
||||
{
|
||||
type: Button,
|
||||
props: {
|
||||
children: 'OK!',
|
||||
color: 'blue'
|
||||
}
|
||||
}
|
||||
|
||||
// React: ...and Button told me this! I guess I'm done.
|
||||
{
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-blue',
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: 'OK!'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is a part of the process that React calls [reconciliation](/react/docs/reconciliation.html) which starts when you call [`ReactDOM.render()`](/react/docs/top-level-api.html#reactdom.render) or [`setState()`](/react/docs/component-api.html#setstate). By the end of the reconciliation, React knows the result DOM tree, and a renderer like `react-dom` or `react-native` applies the minimal set of changes necessary to update the DOM nodes (or the platform-specific views in case of React Native).
|
||||
|
||||
This gradual refining process is also the reason React apps are easy to optimize. If some parts of your component tree become too large for React to visit efficiently, you can tell it to [skip this “refining” and diffing certain parts of the tree if the relevant props have not changed](/react/docs/advanced-performance.html). It is very fast to calculate whether the props have changed if they are immutable, so React and immutability work great together, and can provide great optimizations with the minimal effort.
|
||||
|
||||
You might have noticed that this blog entry talks a lot about components and elements, and not so much about the instances. The truth is, instances have much less importance in React than in most object-oriented UI frameworks.
|
||||
|
||||
Only components declared as classes have instances, and you never create them directly: React does that for you. While [mechanisms for a parent component instance to access a child component instance](/react/docs/more-about-refs.html) exist, they are only used for imperative actions (such as setting focus on a field), and should generally be avoided.
|
||||
|
||||
React takes care of creating an instance for every class component, so you can write components in an object-oriented way with methods and local state, but other than that, instances are not very important in the React’s programming model and are managed by React itself.
|
||||
|
||||
## Summary
|
||||
|
||||
An *element* is a plain object describing what you want to appear on the screen in terms of the DOM nodes or other components. Elements can contain other elements in their props. Creating a React element is cheap. Once an element is created, it is never mutated.
|
||||
|
||||
A *component* can be declared in several different ways. It can be a class with a `render()` method. Alternatively, in simple cases, it can be defined as a function. In either case, it takes props as an input, and returns an element tree as the output.
|
||||
|
||||
When a component receives some props as an input, it is because a particular parent component returned an element with its `type` and these props. This is why people say that the props flows one way in React: from parents to children.
|
||||
|
||||
An *instance* is what you refer to as `this` in the component class you write. It is useful for [storing local state and reacting to the lifecycle events](/react/docs/component-api.html).
|
||||
|
||||
Functional components don’t have instances at all. Class components have instances, but you never need to create a component instance directly—React takes care of this.
|
||||
|
||||
Finally, to create elements, use [`React.createElement()`](/react/docs/top-level-api.html#react.createelement), [JSX](/react/docs/jsx-in-depth.html), or an [element factory helper](/react/docs/top-level-api.html#react.createfactory). Don’t write elements as plain objects in the real code—just know that they are plain objects under the hood.
|
||||
|
||||
## Further Reading
|
||||
|
||||
* [Introducing React Elements](/react/blog/2014/10/14/introducing-react-elements.html)
|
||||
* [Streamlining React Elements](/react/blog/2015/02/24/streamlining-react-elements.html)
|
||||
* [React (Virtual) DOM Terminology](/react/docs/glossary.html)
|
||||
|
||||
[^1]: All React elements require an additional ``$$typeof: Symbol.for('react.element')`` field declared on the object for [security reasons](https://github.com/facebook/react/pull/4832). It is omitted in the examples above. This blog entry uses inline objects for elements to give you an idea of what’s happening underneath but the code won’t run as is unless you either add `$$typeof` to the elements, or change the code to use `React.createElement()` or JSX.
|
||||
37
docs/_posts/2015-12-29-react-v0.14.4.md
Normal file
37
docs/_posts/2015-12-29-react-v0.14.4.md
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "React v0.14.4"
|
||||
author: spicyj
|
||||
---
|
||||
|
||||
Happy December! We have a minor point release today. It has just a few small bug fixes.
|
||||
|
||||
The release is now available for download:
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-0.14.4.js>
|
||||
Minified build for production: <https://fb.me/react-0.14.4.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-0.14.4.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-0.14.4.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-0.14.4.js>
|
||||
Minified build for production: <https://fb.me/react-dom-0.14.4.min.js>
|
||||
* **React DOM Server** (include React in the page before React DOM Server)
|
||||
Dev build with warnings: <https://fb.me/react-dom-server-0.14.4.js>
|
||||
Minified build for production: <https://fb.me/react-dom-server-0.14.4.min.js>
|
||||
|
||||
We've also published version `0.14.4` of the `react`, `react-dom`, and addons packages on npm and the `react` package on bower.
|
||||
|
||||
- - -
|
||||
|
||||
## Changelog
|
||||
|
||||
### React
|
||||
- Minor internal changes for better compatibility with React Native
|
||||
|
||||
### React DOM
|
||||
- The `autoCapitalize` and `autoCorrect` props are now set as attributes in the DOM instead of properties to improve cross-browser compatibility
|
||||
- Fixed bug with controlled `<select>` elements not handling updates properly
|
||||
|
||||
### React Perf Add-on
|
||||
- Some DOM operation names have been updated for clarity in the output of `.printDOM()`
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: "(A => B) !=> (B => A)"
|
||||
author: jimfb
|
||||
---
|
||||
|
||||
The documentation for `componentWillReceiveProps` states that `componentWillReceiveProps` will be invoked when the props change as the result of a rerender. Some people assume this means "if `componentWillReceiveProps` is called, then the props must have changed", but that conclusion is logically incorrect.
|
||||
|
||||
The guiding principle is one of my favorites from formal logic/mathematics:
|
||||
> A implies B does not imply B implies A
|
||||
|
||||
Example: "If I eat moldy food, then I will get sick" does not imply "if I am sick, then I must have eaten moldy food". There are many other reasons I could be feeling sick. For instance, maybe the flu is circulating around the office. Similarly, there are many reasons that `componentWillReceiveProps` might get called, even if the props didn’t change.
|
||||
|
||||
If you don’t believe me, call `ReactDOM.render()` three times with the exact same props, and try to predict the number of times `componentWillReceiveProps` will get called:
|
||||
|
||||
|
||||
```js
|
||||
class Component extends React.Component {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
console.log('componentWillReceiveProps', nextProps.data.bar);
|
||||
}
|
||||
render() {
|
||||
return <div>Bar {this.props.data.bar}!</div>;
|
||||
}
|
||||
}
|
||||
|
||||
var container = document.getElementById('container');
|
||||
|
||||
var mydata = {bar: 'drinks'};
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
```
|
||||
|
||||
|
||||
In this case, the answer is "2". React calls `componentWillReceiveProps` twice (once for each of the two updates). Both times, the value of "drinks" is printed (ie. the props didn’t change).
|
||||
|
||||
To understand why, we need to think about what *could* have happened. The data *could* have changed between the initial render and the two subsequent updates, if the code had performed a mutation like this:
|
||||
|
||||
```js
|
||||
var mydata = {bar: 'drinks'};
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
mydata.bar = 'food'
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
mydata.bar = 'noise'
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
```
|
||||
|
||||
React has no way of knowing that the data didn’t change. Therefore, React needs to call `componentWillReceiveProps`, because the component needs to be notified of the new props (even if the new props happen to be the same as the old props).
|
||||
|
||||
You might think that React could just use smarter checks for equality, but there are some issues with this idea:
|
||||
|
||||
* The old `mydata` and the new `mydata` are actually the same physical object (only the object’s internal value changed). Since the references are triple-equals-equal, doing an equality check doesn’t tell us if the value has changed. The only possible solution would be to have created a deep copy of the data, and then later do a deep comparison - but this can be prohibitively expensive for large data structures (especially ones with cycles).
|
||||
* The `mydata` object might contain references to functions which have captured variables within closures. There is no way for React to peek into these closures, and thus no way for React to copy them and/or verify equality.
|
||||
* The `mydata` object might contain references to objects which are re-instantiated during the parent's render (ie. not triple-equals-equal) but are conceptually equal (ie. same keys and same values). A deep-compare (expensive) could detect this, except that functions present a problem again because there is no reliable way to compare two functions to see if they are semantically equivalent.
|
||||
|
||||
Given the language constraints, it is sometimes impossible for us to achieve meaningful equality semantics. In such cases, React will call `componentWillReceiveProps` (even though the props might not have changed) so the component has an opportunity to examine the new props and act accordingly.
|
||||
|
||||
As a result, your implementation of `componentWillReceiveProps` MUST NOT assume that your props have changed. If you want an operation (such as a network request) to occur only when props have changed, your `componentWillReceiveProps` code needs to check to see if the props actually changed.
|
||||
|
||||
|
||||
10
docs/_posts/2016-01-12-discontinuing-ie8-support.md
Normal file
10
docs/_posts/2016-01-12-discontinuing-ie8-support.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "Discontinuing IE 8 Support in React DOM"
|
||||
author: spicyj
|
||||
---
|
||||
|
||||
Since its 2013 release, React has supported all popular browsers, including Internet Explorer 8 and above. We handle normalizing many quirks present in old browser versions, including event system differences, so that your app code doesn't have to worry about most browser bugs.
|
||||
|
||||
Today, Microsoft [discontinued support for older versions of IE](https://www.microsoft.com/en-us/WindowsForBusiness/End-of-IE-support). Starting with React v15, we're discontinuing React DOM's support for IE 8. We've heard that most React DOM apps already don't support old versions of Internet Explorer, so this shouldn't affect many people. This change will help us develop faster and make React DOM even better. (We won't actively remove IE 8–related code quite yet, but we will deprioritize new bugs that are reported. If you need to support IE 8 we recommend you stay on React v0.14.)
|
||||
|
||||
React DOM will continue to support IE 9 and above for the foreseeable future.
|
||||
60
docs/_posts/2016-02-19-new-versioning-scheme.md
Normal file
60
docs/_posts/2016-02-19-new-versioning-scheme.md
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: "New Versioning Scheme"
|
||||
author: sebmarkbage
|
||||
---
|
||||
|
||||
Today we're announcing that we're switching to major revisions for React. The current version is 0.14.7. The next release will be: **15.0.0**
|
||||
|
||||
This change shouldn't materially affect most of you. Moving to major semver versions simply helps indicate our commitment to stability and gives us the flexibility to add new backwards-compatible features in minor releases. This means we can have fewer major releases and you won't have to wait as long to take advantage of improvements to React. Plus, if you're a component author, this versioning scheme gives you the flexibility to support two major versions of React at the same time so you don't need to leave anyone behind.
|
||||
|
||||
The core of the React API has been stable for years. Our business as well as many of yours all depend heavily on the use of React as a core piece of our infrastructure. We're committed to the stability as well as the progress of React going forward.
|
||||
|
||||
## Bring Everyone Along
|
||||
|
||||
React isn't just a library but an ecosystem. We know that your applications and ours are not just isolated islands of code. It is a network of your own application code, your own open source components and third party libraries that all depend on React.
|
||||
|
||||
<img src="/react/img/blog/versioning-1.png" width="403">
|
||||
|
||||
Therefore it is important that we don't just upgrade our own codebases but that we bring our whole community with us. We take the upgrade path very seriously - for everyone.
|
||||
|
||||
<img src="/react/img/blog/versioning-poll.png" width="596">
|
||||
|
||||
## Introducing Minor Releases
|
||||
|
||||
Ideally everyone could just depend on the latest version of React all the time.
|
||||
|
||||
<img src="/react/img/blog/versioning-2.png" width="463">
|
||||
|
||||
We know that in practice that is not possible. In the future, we expect more new additive APIs rather than breakage of existing ones. By moving to major revisions in the semver scheme, we can release new versions without breaking existing ones.
|
||||
|
||||
<img src="/react/img/blog/versioning-3.png" width="503">
|
||||
|
||||
That means that if one component needs a new API, there is no need for any of the other components to do any further work. They remain compatible.
|
||||
|
||||
## What Happened to 1.0.0?
|
||||
|
||||
Part of React's growth and popularity is that it is stable and performant in production. People have long asked what React v1.0 will look. Technically some breaking changes are important to avoid stagnating, but we still achieve stability by making it easy to upgrade. If major version numbers indicate API stability and engender trust that it can be used in production, then we got there a long time ago. There are too many preconceived notions of what v1.0 is. We're still following semver. We're just communicating stability by moving the 0 from the beginning to the end.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
Minor revision releases will include deprecation warnings and tips for how to upgrade an API or pattern that will be removed or changed in the future.
|
||||
|
||||
We will continue to release [codemods](https://www.youtube.com/watch?v=d0pOgY8__JM) for common patterns to make automatic upgrades of your codebase easier.
|
||||
|
||||
Once we've reached the end of life for a particular major version, we'll release a new major version where all deprecated APIs have been removed.
|
||||
|
||||
## Avoiding The Major Cliff
|
||||
|
||||
If you try to upgrade your component to 16.0.0 you might find that your application no longer works if you still have other dependencies. E.g. if Ryan's and Jed's components are only compatible with 15.x.x.
|
||||
|
||||
<img src="/react/img/blog/versioning-4.png" width="498">
|
||||
|
||||
Worst case, you revert back to 15.1.0 for your application. Since you'll want to use your component, you might also revert that one.
|
||||
|
||||
<img src="/react/img/blog/versioning-5.png" width="493">
|
||||
|
||||
Of course, Ryan and Jed think the same way. If we're not careful, we can hit a cliff where nobody upgrades. This has happened to many software project ecosystems in the past.
|
||||
|
||||
Therefore, we're committed to making it easy for most components and libraries built on top of React to be compatible with two major versions at the same time. We will do this by introducing new APIs before completely removing the old ones, thereby avoiding those cliffs.
|
||||
|
||||
<img src="/react/img/blog/versioning-6.png" width="493">
|
||||
96
docs/_posts/2016-03-07-react-v15-rc1.md
Normal file
96
docs/_posts/2016-03-07-react-v15-rc1.md
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
title: "React v15.0 Release Candidate"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
Sorry for the small delay in releasing this. As we said, we've been busy binge-watching House of Cards. That scene in the last episode where Francis and Claire Underwood <abbr title="You didn't think we would actually spoil anything did you?">████████████████████████████████████</abbr>. WOW!
|
||||
|
||||
But now we're ready, so without further ado, we're shipping a release candidate for React v15 now. As a reminder, [we're switching to major versions](/react/blog/2016/02/19/new-versioning-scheme.html) to indicate that we have been using React in production for a long time. This 15.0 release follows our previous 0.14 version and we'll continue to follow semver like we've been doing since 2013. It's also worth noting that [we no longer actively support Internet Explorer 8](/react/blog/2016/01/12/discontinuing-ie8-support.html). We believe React will work in its current form there but we will not be prioritizing any efforts to fix new issues that only affect IE8.
|
||||
|
||||
Please try it out before we publish the final release. Let us know if you run into any problems by filing issues on our [GitHub repo](https://github.com/facebook/react).
|
||||
|
||||
## Upgrade Guide
|
||||
|
||||
Like always, we have a few breaking changes in this release. We know changes can be painful (the Facebook codebase has over 15,000 React components), so we always try to make changes gradually in order to minimize the pain.
|
||||
|
||||
If your code is free of warnings when running under React 0.14, upgrading should be easy. The bulk of changes in this release are actually behind the scenes, impacting the way that React interacts with the DOM. The other substantial change is that React now supports the full range of SVG elements and attributes. Beyond that we have a large number of incremental improvements and additional warnings aimed to aid developers. We've also laid some groundwork in the core to bring you some new capabilities in future releases.
|
||||
|
||||
See the changelog below for more details.
|
||||
|
||||
## Installation
|
||||
|
||||
We recommend using React from `npm` and using a tool like browserify or webpack to build your code into a single bundle. To install the two packages:
|
||||
|
||||
* `npm install --save react@15.0.0-rc.1 react-dom@15.0.0-rc.1`
|
||||
|
||||
Remember that by default, React runs extra checks and provides helpful warnings in development mode. When deploying your app, set the `NODE_ENV` environment variable to `production` to use the production build of React which does not include the development warnings and runs significantly faster.
|
||||
|
||||
If you can’t use `npm` yet, we provide pre-built browser builds for your convenience, which are also available in the `react` package on bower.
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-15.0.0-rc.1.js>
|
||||
Minified build for production: <https://fb.me/react-15.0.0-rc.1.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-15.0.0-rc.1.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-15.0.0-rc.1.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-15.0.0-rc.1.js>
|
||||
Minified build for production: <https://fb.me/react-dom-15.0.0-rc.1.min.js>
|
||||
|
||||
## Changelog
|
||||
|
||||
### Major changes
|
||||
|
||||
- #### `document.createElement` is in and `data-reactid` is out
|
||||
|
||||
There were a number of large changes to our interactions with the DOM. One of the most noticeable changes is that we no longer set the `data-reactid` attribute for each DOM node. While this will make it much more difficult to know if a website is using React, the advantage is that the DOM is much more lightweight. This change was made possible by us switching to use `document.createElement` on initial render. Previously we would generate a large string of HTML and then set `node.innerHTML`. At the time, this was decided to be faster than using `document.createElement` for the majority of cases and browsers that we supported. Browsers have continued to improve and so overwhelmingly this is no longer true. By using `createElement` we can make other parts of React faster. The ids were used to map back from events to the original React component, meaning we had to do a bunch of work on every event, even though we cached this data heavily. As we've all experienced, caching and in particularly invalidating caches, can be error prone and we saw many hard to reproduce issues over the years as a result. Now we can build up a direct mapping at render time since we already have a handle on the node.
|
||||
|
||||
- #### No more extra `<span>`s
|
||||
|
||||
Another big change with our DOM interaction is how we render text blocks. Previously you may have noticed that React rendered a lot of extra `<span>`s. Eg, in our most basic example on the home page we render `<div>Hello {this.props.name}</div>`, resulting in markup that contained 2 `<span>`s. Now we'll render plain text nodes interspersed with comment nodes that are used for demarcation. This gives us the same ability to update individual pieces of text, without creating extra nested nodes. Very few people have depended on the actual markup generated here so it's likely you are not impacted. However if you were targeting these `<span>`s in your CSS, you will need to adjust accordingly. You can always render them explicitly in your components.
|
||||
|
||||
- #### Rendering `null` now uses comment nodes
|
||||
|
||||
We've also made use of these comment nodes to change what `null` renders to. Rendering to `null` was a feature we added in React v0.11 and was implemented by rendering `<noscript>` elements. By rendering to comment nodes now, there's a chance some of your CSS will be targeting the wrong thing, specifically if you are making use of `:nth-child` selectors. This, along with the other changes mentioned above, have always been considered implementation details of how React targets the DOM. We believe they are safe changes to make without going through a release with warnings detailing the subtle differences as they are details that should not be depended upon. Additionally, we have seen that these changes have improved React performance for many typical applications.
|
||||
|
||||
- #### Improved SVG support
|
||||
|
||||
All SVG tags and attributes are now fully supported. (Uncommon SVG tags are not present on the `React.DOM` element helper, but JSX and `React.createElement` work on all tag names.) All SVG attributes match their original capitalization and hyphenation as defined in the specification (ex: `gradientTransform` must be camel-cased but `clip-path` should be hyphenated).
|
||||
|
||||
|
||||
|
||||
### Breaking changes
|
||||
|
||||
It's worth calling out the DOM structure changes above again, in particular the change from `<span>`s. In the course of updating the Facebook codebase, we found a very small amount of code that was depending on the markup that React generated. Some of these cases were integration tests like WebDriver which were doing very specific XPath queries to target nodes. Others were simply tests using `ReactDOM.renderToStaticMarkup` and comparing markup. Again, there were a very small number of changes that had to be made, but we don't want anybody to be blindsided. We encourage everybody to run their test suites when upgrading and consider alternative approaches when possible. One approach that will work for some cases is to explicitly use `<span>`s in your `render` method.
|
||||
|
||||
These deprecations were introduced in v0.14 with a warning and the APIs are now removed.
|
||||
|
||||
- Deprecated APIs removed from `React`, specifically `findDOMNode`, `render`, `renderToString`, `renderToStaticMarkup`, and `unmountComponentAtNode`.
|
||||
- Deprecated APIs removed from `React.addons`, specifically `batchedUpdates` and `cloneWithProps`.
|
||||
- Deprecated APIs removed from component instances, specifically `setProps`, `replaceProps`, and `getDOMNode`.
|
||||
|
||||
### New deprecations, introduced with a warning
|
||||
|
||||
Each of these changes will continue to work as before with a new warning until the release of React 16 so you can upgrade your code gradually.
|
||||
|
||||
- `LinkedStateMixin` and `valueLink` are now deprecated due to very low popularity. If you need this, you can use a wrapper component that implements the same behavior: [react-linked-input](https://www.npmjs.com/package/react-linked-input).
|
||||
|
||||
|
||||
### New helpful warnings
|
||||
|
||||
- If you use a minified copy of the _development_ build, React DOM kindly encourages you to use the faster production build instead.
|
||||
- React DOM: When specifying a unit-less CSS value as a string, a future version will not add `px` automatically. This version now warns in this case (ex: writing `style={{'{{'}}width: '300'}}`. (Unitless *number* values like `width: 300` are unchanged.)
|
||||
- Synthetic Events will now warn when setting and accessing properties (which will not get cleared appropriately), as well as warn on access after an event has been returned to the pool.
|
||||
- Elements will now warn when attempting to read `ref` and `key` from the props.
|
||||
- React DOM now attempts to warn for mistyped event handlers on DOM elements (ex: `onclick` which should be `onClick`)
|
||||
|
||||
### Notable bug fixes
|
||||
|
||||
- Fixed multiple small memory leaks
|
||||
- Click events are handled by React DOM more reliably in mobile browsers, particularly in Mobile Safari.
|
||||
- Input events are handled more reliably in IE 10 and IE 11; spurious events no longer fire when using a placeholder.
|
||||
- React DOM now supports the `cite` and `profile` HTML attributes.
|
||||
- React DOM now supports the `onAnimationStart`, `onAnimationEnd`, `onAnimationIteration`, `onTransitionEnd`, and `onInvalid` events. Support for `onLoad` has been added to `object` elements.
|
||||
- Add-Ons: ReactTransitionGroup now correctly handles multiple nodes being removed simultaneously.
|
||||
- `Object.is` is used in a number of places to compare values, which leads to fewer false positives, especially involving `NaN`. In particular, this affects the `shallowCompare` add-on.
|
||||
- React DOM now defaults to using DOM attributes instead of properties, which fixes a few edge case bugs. Additionally the nullification of values (ex: `href={null}`) now results in the forceful removal, no longer trying to set to the default value used by browsers in the absence of a value.
|
||||
32
docs/_posts/2016-03-16-react-v15-rc2.md
Normal file
32
docs/_posts/2016-03-16-react-v15-rc2.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: "React v15.0 Release Candidate 2"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
Today we're releasing a second release candidate for version 15. Primarily this is to address 2 issues, but we also picked up a few small changes from new contributors, including some improvements to some of our new warnings.
|
||||
|
||||
The most pressing change that was made is to fix a bug in our new code that removes `<span>`s, as discussed in the original RC1 post. Specifically we have some code that takes a different path in IE11 and Edge due to the speed of some DOM operations. There was a bug in this code which didn't break out of the optimization for `DocumentFragment`s, resulting in text not appearing at all. Thanks to the several people who [reported this](https://github.com/facebook/react/issues/6246).
|
||||
|
||||
The other change is to our SVG code. In RC1 we had made the decision to pass through all attributes directly. This led to [some confusion with `class` vs `className`](https://github.com/facebook/react/issues/6211) and ultimately led us to reconsider our position on the approach. Passing through all attributes meant that we would have two different patterns for using React where things like hyphenated attributes would work for SVG but not HTML. In the future, we *might* change our approach to the problem for HTML as well but in the meantime, maintaining consistency is important. So we reverted the changes that allowed the attributes to be passed through and instead expanded the SVG property list to include all attributes that are in the spec. We believe we have everything now but definitely [let us know](https://github.com/facebook/react/issues/1657#issuecomment-197031403) if we missed anything. It was and still is our intent to support the full range of SVG tags and attributes in this release.
|
||||
|
||||
Thanks again to everybody who has tried the RC1 and reported issues. It has been extremely important and we wouldn't be able to do this without your help!
|
||||
|
||||
## Installation
|
||||
|
||||
We recommend using React from `npm` and using a tool like browserify or webpack to build your code into a single bundle. To install the two packages:
|
||||
|
||||
* `npm install --save react@15.0.0-rc.2 react-dom@15.0.0-rc.2`
|
||||
|
||||
Remember that by default, React runs extra checks and provides helpful warnings in development mode. When deploying your app, set the `NODE_ENV` environment variable to `production` to use the production build of React which does not include the development warnings and runs significantly faster.
|
||||
|
||||
If you can’t use `npm` yet, we provide pre-built browser builds for your convenience, which are also available in the `react` package on bower.
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-15.0.0-rc.2.js>
|
||||
Minified build for production: <https://fb.me/react-15.0.0-rc.2.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-15.0.0-rc.2.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-15.0.0-rc.2.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-15.0.0-rc.2.js>
|
||||
Minified build for production: <https://fb.me/react-dom-15.0.0-rc.2.min.js>
|
||||
@@ -16,4 +16,8 @@ We'd like to thank all of our contributors:
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
In addition, we're grateful to [Jeff Barczewski](https://github.com/jeffbski) for allowing us to use the [react](https://www.npmjs.com/package/react) package name on npm and to [Christopher Aue](http://christopheraue.net/) for letting us use the [reactjs.com](http://reactjs.com/) domain name and the [@reactjs](https://twitter.com/reactjs) username on Twitter. We'd also like to thank [ProjectMoon](https://github.com/ProjectMoon) for letting us use the [flux](https://www.npmjs.com/package/flux) package name on npm.
|
||||
In addition, we're grateful to
|
||||
- [Jeff Barczewski](https://github.com/jeffbski) for allowing us to use the [react](https://www.npmjs.com/package/react) package name on npm.
|
||||
- [Christopher Aue](http://christopheraue.net/) for letting us use the [reactjs.com](http://reactjs.com/) domain name and the [@reactjs](https://twitter.com/reactjs) username on Twitter.
|
||||
- [ProjectMoon](https://github.com/ProjectMoon) for letting us use the [flux](https://www.npmjs.com/package/flux) package name on npm.
|
||||
- Shane Anderson for allowing us to use the [react](https://github.com/react) org on GitHub.
|
||||
|
||||
@@ -129,7 +129,7 @@ h1, h2, h3, h4, h5, h6 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
li > a {
|
||||
box-sizing: content-box;
|
||||
padding: 0 10px;
|
||||
line-height: $navHeight;
|
||||
@@ -260,6 +260,22 @@ h1, h2, h3, h4, h5, h6 {
|
||||
&.active {
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
&.external {
|
||||
&:after {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
padding-left: 5px;
|
||||
@include retina-image('../img/external', 10px 10px);
|
||||
background-position: 100% 0;
|
||||
background-repeat: no-repeat;
|
||||
font-size: 10px;
|
||||
line-height: 1em;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-docs-section {
|
||||
@@ -409,6 +425,7 @@ h1, h2, h3, h4, h5, h6 {
|
||||
.playgroundPreview {
|
||||
padding: 0;
|
||||
width: 600px;
|
||||
word-wrap: break-word;
|
||||
|
||||
pre {
|
||||
@include code-typography;
|
||||
@@ -837,3 +854,72 @@ div[data-twttr-id] iframe {
|
||||
.three-column > ul:first-child {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
|
||||
/* Algolia Doc Search */
|
||||
|
||||
@media screen and (max-width: 960px) {
|
||||
#algolia-doc-search {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
input#algolia-doc-search {
|
||||
background: transparent url('/react/img/search.png') no-repeat 10px center;
|
||||
background-size: 16px 16px;
|
||||
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
margin-left: 10px;
|
||||
padding: 0 10px;
|
||||
padding-left: 35px;
|
||||
height: 30px;
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
background-color: #333;
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
outline: none;
|
||||
width: 170px;
|
||||
|
||||
transition: width .2s ease;
|
||||
}
|
||||
|
||||
input#algolia-doc-search:focus {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.algolia-autocomplete .aa-dropdown-menu {
|
||||
margin-left: -110px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.algolia-autocomplete {
|
||||
vertical-align: top;
|
||||
height: 53px;
|
||||
}
|
||||
|
||||
.algolia-docsearch-suggestion {
|
||||
border-bottom-color: #c05b4d;
|
||||
}
|
||||
|
||||
.algolia-docsearch-suggestion--category-header {
|
||||
background-color: #cc7a6f;
|
||||
}
|
||||
|
||||
.algolia-docsearch-suggestion--highlight {
|
||||
color: #c05b4d;
|
||||
}
|
||||
|
||||
.algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--highlight {
|
||||
background-color: #c05b4d;
|
||||
}
|
||||
|
||||
.aa-cursor .algolia-docsearch-suggestion--content {
|
||||
color: #c05b4d;
|
||||
}
|
||||
|
||||
.aa-cursor .algolia-docsearch-suggestion {
|
||||
background: #f1f3f5;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ title: 为什么使用 React?
|
||||
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 是为了解决一个问题:**构建随着时间数据不断变化的大规模应用程序**。
|
||||
@@ -28,5 +27,3 @@ React挑战了很多传统的知识,第一眼看上去可能很多想法有点
|
||||
## 了解更多
|
||||
|
||||
你可以从这篇[博客](/react/blog/2013/06/05/why-react.html)了解更多我们创造 React 的动机。
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
id: displaying-data-zh-CN
|
||||
title: 显示数据
|
||||
layout: docs
|
||||
permalink: displaying-data-zh-CN.html
|
||||
prev: why-react-zh-CN.html
|
||||
next: jsx-in-depth-zh-CN.html
|
||||
@@ -9,7 +8,6 @@ next: jsx-in-depth-zh-CN.html
|
||||
|
||||
用户界面能做的最基础的事就是显示一些数据。React 让显示数据变得简单,当数据变化的时候,用户界面会自动同步更新。
|
||||
|
||||
|
||||
## 开始
|
||||
|
||||
让我们看一个非常简单的例子。新建一个名为 `hello-react.html` 的文件,代码内容如下:
|
||||
@@ -57,7 +55,6 @@ setInterval(function() {
|
||||
}, 500);
|
||||
```
|
||||
|
||||
|
||||
## 被动更新 (Reactive Updates)
|
||||
|
||||
在浏览器中打开 `hello-react.html` ,在输入框输入你的名字。你会发现 React 在用户界面中只改变了时间, 任何你在输入框输入的内容一直保留着,即使你没有写任何代码来完成这个功能。React 为你解决了这个问题,做了正确的事。
|
||||
@@ -66,7 +63,6 @@ setInterval(function() {
|
||||
|
||||
对这个组件的输入称为 `props` - "properties"的缩写。得益于 JSX 语法,它们通过参数传递。你必须知道在组件里,这些属性是不可改变的,也就是说 **`this.props` 是只读的**。
|
||||
|
||||
|
||||
## 组件就像是函数
|
||||
|
||||
React 组件非常简单。你可以认为它们就是简单的函数,接受 `props` 和 `state` (后面会讨论) 作为参数,然后渲染出 HTML。正是应为它们是这么的简单,这使得它们非常容易理解。
|
||||
@@ -75,12 +71,13 @@ React 组件非常简单。你可以认为它们就是简单的函数,接受 `
|
||||
>
|
||||
> **只有一个限制**: React 组件只能渲染单个根节点。如果你想要返回多个节点,它们*必须*被包含在同一个节点里。
|
||||
|
||||
|
||||
## JSX 语法
|
||||
|
||||
我们坚信组件是正确方法去做关注分离,而不是通过“模板”和“展示逻辑”。我们认为标签和生成它的代码是紧密相连的。此外,展示逻辑通常是很复杂的,通过模板语言实现这些逻辑会产生大量代码。
|
||||
|
||||
我们得出解决这个问题最好的方案是通过 JavaScript 直接生成模板,这样你就可以用一个真正语言的所有表达能力去构建用户界面。为了使这变得更简单,我们做了一个非常简单、**可选**类似 HTML 语法 ,通过函数调用即可生成模板的编译器,称为 JSX。
|
||||
我们得出解决这个问题最好的方案是通过 JavaScript 直接生成模板,这样你就可以用一个真正语言的所有表达能力去构建用户界面。
|
||||
|
||||
为了使这变得更简单,我们做了一个非常简单、**可选**类似 HTML 语法 ,通过函数调用即可生成模板的编译器,称为 JSX。
|
||||
|
||||
**JSX 让你可以用 HTML 语法去写 JavaScript 函数调用** 为了在 React 生成一个链接,通过纯 JavaScript 你可以这么写:
|
||||
|
||||
@@ -100,7 +97,7 @@ JSX 类似于 HTML,但不是完全一样。参考 [JSX 陷阱](/react/docs/jsx
|
||||
|
||||
## 没有 JSX 的 React
|
||||
|
||||
JSX完全是可选的;你无需在 React 中必须使用 JSX。你可以通过 `React.createElement` 来创建一个树。第一个参数是标签,第二个参数是一个属性对象,每三个是子节点。
|
||||
JSX完全是可选的;你无需在 React 中必须使用 JSX。你可以通过 `React.createElement` 来创建一个树。第一个参数是标签,第二个参数是一个属性对象,第三个是子节点。
|
||||
|
||||
```javascript
|
||||
var child1 = React.createElement('li', null, 'First Text Content');
|
||||
@@ -125,4 +122,3 @@ var root = React.DOM.ul({ className: 'my-list' },
|
||||
React.DOM.li(null, 'Text Content')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
@@ -82,10 +82,7 @@ var Nav = React.createClass({ });
|
||||
var Nav = React.createClass({displayName: "Nav", });
|
||||
```
|
||||
|
||||
Use the [Babel REPL](https://babeljs.io/repl/) to try out JSX and see how it
|
||||
desugars into native JavaScript, and the
|
||||
[HTML to JSX converter](/react/html-jsx.html) to convert your existing HTML to
|
||||
JSX.
|
||||
Use the [Babel REPL](https://babeljs.io/repl/) to try out JSX and see how it desugars into native JavaScript, and the [HTML to JSX converter](/react/html-jsx.html) to convert your existing HTML to JSX.
|
||||
|
||||
If you want to use JSX, the [Getting Started](/react/docs/getting-started.html) guide shows how to set up compilation.
|
||||
|
||||
@@ -163,8 +160,7 @@ var App = (
|
||||
|
||||
### Attribute Expressions
|
||||
|
||||
To use a JavaScript expression as an attribute value, wrap the expression in a
|
||||
pair of curly braces (`{}`) instead of quotes (`""`).
|
||||
To use a JavaScript expression as an attribute value, wrap the expression in a pair of curly braces (`{}`) instead of quotes (`""`).
|
||||
|
||||
```javascript
|
||||
// Input (JSX):
|
||||
|
||||
@@ -8,7 +8,6 @@ next: jsx-spread-zh-CN.html
|
||||
|
||||
[JSX](https://facebook.github.io/jsx/) 是一个看起来很像 XML 的 JavaScript 语法扩展。React 可以用来做简单的 JSX 句法转换。
|
||||
|
||||
|
||||
## 为什么要用 JSX?
|
||||
|
||||
你不需要为了 React 使用 JSX,可以直接使用原生 JS。但是,我们建议使用 JSX 是因为它能精确,也是常用的定义包含属性的树状结构的语法。
|
||||
@@ -46,7 +45,6 @@ React 的 JSX 使用大、小写的约定来区分本地组件的类和 HTML 标
|
||||
> 由于 JSX 就是 JavaScript,一些标识符像 `class` 和 `for` 不建议作为 XML
|
||||
> 属性名。作为替代,React DOM 使用 `className` 和 `htmlFor` 来做对应的属性。
|
||||
|
||||
|
||||
## 转换(Transform)
|
||||
|
||||
JSX 把类 XML 的语法转成原生 JavaScript,XML 元素、属性和子节点被转换成 `React.createElement` 的参数。
|
||||
@@ -90,6 +88,7 @@ var Nav = React.createClass({displayName: "Nav", });
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>
|
||||
> JSX 表达式总是会当作 ReactElement 执行。具体的实际细节可能不同。一种优化
|
||||
> 的模式是把 ReactElement 当作一个行内的对象字面量形式来绕过
|
||||
> `React.createElement` 里的校验代码。
|
||||
|
||||
@@ -49,4 +49,4 @@ You can use this multiple times or combine it with other attributes. The specifi
|
||||
|
||||
## What's with the weird `...` notation?
|
||||
|
||||
The `...` operator (or spread operator) is already supported for [arrays in ES6](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator). There is also an ES7 proposal for [Object Rest and Spread Properties](https://github.com/sebmarkbage/ecmascript-rest-spread). We're taking advantage of these supported and developing standards in order to provide a cleaner syntax in JSX.
|
||||
The `...` operator (or spread operator) is already supported for [arrays in ES6](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator). There is also an ECMAScript proposal for [Object Rest and Spread Properties](https://github.com/sebmarkbage/ecmascript-rest-spread). We're taking advantage of these supported and developing standards in order to provide a cleaner syntax in JSX.
|
||||
|
||||
@@ -12,7 +12,6 @@ next: jsx-gotchas-zh-CN.html
|
||||
var component = <Component foo={x} bar={y} />;
|
||||
```
|
||||
|
||||
|
||||
## 修改 Props 是不好的,明白吗
|
||||
|
||||
如果你不知道要设置哪些 Props,那么现在最好不要设置它:
|
||||
@@ -27,7 +26,6 @@ next: jsx-gotchas-zh-CN.html
|
||||
|
||||
Props 应该被认为是不可变的。在别处修改 props 对象可能会导致预料之外的结果,所以原则上这将是一个冻结的对象。
|
||||
|
||||
|
||||
## 展开属性(Spread Attributes)
|
||||
|
||||
现在你可以使用 JSX 的新特性 - 展开属性:
|
||||
@@ -49,7 +47,6 @@ Props 应该被认为是不可变的。在别处修改 props 对象可能会导
|
||||
console.log(component.props.foo); // 'override'
|
||||
```
|
||||
|
||||
|
||||
## 这个奇怪的 `...` 标记是什么?
|
||||
|
||||
这个 `...` 操作符(增强的操作符)已经被 [ES6 数组](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) 支持。相关的还有 ES7 规范草案中的 [Object 剩余和展开属性(Rest and Spread Properties)](https://github.com/sebmarkbage/ecmascript-rest-spread)。我们利用了这些还在制定中标准中已经被支持的特性来使 JSX 拥有更优雅的语法。
|
||||
这个 `...` 操作符(增强的操作符)已经被 [ES6 数组](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) 支持。相关的还有 ECMAScript 规范草案中的 [Object 剩余和展开属性(Rest and Spread Properties)](https://github.com/sebmarkbage/ecmascript-rest-spread)。我们利用了这些还在制定中标准中已经被支持的特性来使 JSX 拥有更优雅的语法。
|
||||
|
||||
@@ -52,6 +52,7 @@ HTML 实体可以插入到 JSX 的文本中。
|
||||
<div dangerouslySetInnerHTML={{'{{'}}__html: 'First · Second'}} />
|
||||
```
|
||||
|
||||
|
||||
## 自定义 HTML 属性
|
||||
|
||||
如果往原生 HTML 元素里传入 HTML 规范里不存在的属性,React 不会显示它们。如果需要使用自定义属性,要加 `data-` 前缀。
|
||||
@@ -60,6 +61,12 @@ HTML 实体可以插入到 JSX 的文本中。
|
||||
<div data-custom-attribute="foo" />
|
||||
```
|
||||
|
||||
然而,在自定义元素中任意的属性都是被支持的 (那些在tag名里带有连接符或者 `is="..."` 属性的)
|
||||
|
||||
```javascript
|
||||
<x-my-component custom-attribute="foo" />
|
||||
```
|
||||
|
||||
以 `aria-` 开头的 [网络无障碍](http://www.w3.org/WAI/intro/aria) 属性可以正常使用。
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -36,7 +36,7 @@ ReactDOM.render(
|
||||
|
||||
## Event Handling and Synthetic Events
|
||||
|
||||
With React you simply pass your event handler as a camelCased prop similar to how you'd do it in normal HTML. React ensures that all events behave identically in IE8 and above by implementing a synthetic event system. That is, React knows how to bubble and capture events according to the spec, and the events passed to your event handler are guaranteed to be consistent with [the W3C spec](http://www.w3.org/TR/DOM-Level-3-Events/), regardless of which browser you're using.
|
||||
With React you simply pass your event handler as a camelCased prop similar to how you'd do it in normal HTML. React ensures that all events behave similarly in all browsers by implementing a synthetic event system. That is, React knows how to bubble and capture events according to the spec, and the events passed to your event handler are guaranteed to be consistent with [the W3C spec](http://www.w3.org/TR/DOM-Level-3-Events/), regardless of which browser you're using.
|
||||
|
||||
## Under the Hood: Autobinding and Event Delegation
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ next: multiple-components-zh-CN.html
|
||||
|
||||
我们已经学习如何使用 React [显示数据](/react/docs/displaying-data-zh-CN.html)。现在让我们来学习如何创建交互式界面。
|
||||
|
||||
|
||||
## 简单例子
|
||||
|
||||
```javascript
|
||||
@@ -35,7 +34,6 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 事件处理与合成事件(Synthetic Events)
|
||||
|
||||
React 里只需把事件处理器(event handler)以骆峰命名(camelCased)形式当作组件的 props 传入即可,就像使用普通 HTML 那样。React 内部创建一套合成事件系统来使所有事件在 IE8 和以上浏览器表现一致。也就是说,React 知道如何冒泡和捕获事件,而且你的事件处理器接收到的 events 参数与 [W3C 规范](http://www.w3.org/TR/DOM-Level-3-Events/) 一致,无论你使用哪种浏览器。
|
||||
@@ -48,19 +46,16 @@ React 里只需把事件处理器(event handler)以骆峰命名(camelCased
|
||||
|
||||
**事件代理 :** React 实际并没有把事件处理器绑定到节点本身。当 React 启动的时候,它在最外层使用唯一一个事件监听器处理所有事件。当组件被加载和卸载时,只是在内部映射里添加或删除事件处理器。当事件触发,React 根据映射来决定如何分发。当映射里处理器时,会当作空操作处理。参考 [David Walsh 很棒的文章](http://davidwalsh.name/event-delegate) 了解这样做高效的原因。
|
||||
|
||||
|
||||
## 组件其实是状态机(State Machines)
|
||||
|
||||
React 把用户界面当作简单状态机。把用户界面想像成拥有不同状态然后渲染这些状态,可以轻松让用户界面和数据保持一致。
|
||||
|
||||
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。React 来决定如何最高效地更新 DOM。
|
||||
|
||||
|
||||
## State 工作原理
|
||||
|
||||
常用的通知 React 数据变化的方法是调用 `setState(data, callback)`。这个方法会合并(merge) `data` 到 `this.state`,并重新渲染组件。渲染完成后,调用可选的 `callback` 回调。大部分情况下不需要提供 `callback`,因为 React 会负责把界面更新到最新状态。
|
||||
|
||||
|
||||
## 哪些组件应该有 State?
|
||||
|
||||
大部分组件的工作应该是从 `props` 里取数据并渲染出来。但是,有时需要对用户输入、服务器请求或者时间变化等作出响应,这时才需要使用 State。
|
||||
@@ -69,16 +64,14 @@ React 里,只需更新组件的 state,然后根据新的 state 重新渲染
|
||||
|
||||
常用的模式是创建多个只负责渲染数据的无状态(stateless)组件,在它们的上层创建一个有状态(stateful)组件并把它的状态通过 `props` 传给子级。这个有状态的组件封装了所有用户的交互逻辑,而这些无状态组件则负责声明式地渲染数据。
|
||||
|
||||
|
||||
## 哪些 *应该* 作为 State?
|
||||
|
||||
**State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据。** 真实的应用中这种数据一般都很小且能被 JSON 序列化。当创建一个状态化的组件时,想象一下表示它的状态最少需要哪些数据,并只把这些数据存入 `this.state`。在 `render()` 里再根据 state 来计算你需要的其它数据。你会发现以这种方式思考和开发程序最终往往是正确的,因为如果在 state 里添加冗余数据或计算所得数据,需要你经常手动保持数据同步,不能让 React 来帮你处理。
|
||||
|
||||
|
||||
## 哪些 *不应该* 作为 State?
|
||||
|
||||
`this.state` 应该仅包括能表示用户界面状态所需的最少数据。因些,它不应该包括:
|
||||
|
||||
* **计算所得数据:** 不要担心根据 state 来预先计算数据 —— 把所有的计算都放到 `render()` 里更容易保证用户界面和数据的一致性。例如,在 state 里有一个数组(listItems),我们要把数组长度渲染成字符串, 直接在 `render()` 里使用 `this.state.listItems.length + ' list items'` 比把它放到 state 里好的多。
|
||||
* **React 组件:** 在 `render()` 里使用当前 props 和 state 来创建它。
|
||||
* **基于 props 的重复数据:** 尽可能使用 props 来作为惟一数据来源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为未来的 props 可能会变化。
|
||||
* **基于 props 的重复数据:** 尽可能使用 props 来作为实际状态的源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为 props 可能因为父组件重绘的结果而变化。
|
||||
|
||||
@@ -14,49 +14,49 @@ By building modular components that reuse other components with well-defined int
|
||||
|
||||
## Composition Example
|
||||
|
||||
Let's create a simple Avatar component which shows a profile picture and username using the Facebook Graph API.
|
||||
Let's create a simple Avatar component which shows a Facebook page picture and name using the Facebook Graph API.
|
||||
|
||||
```javascript
|
||||
var Avatar = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ProfilePic username={this.props.username} />
|
||||
<ProfileLink username={this.props.username} />
|
||||
<PagePic pagename={this.props.pagename} />
|
||||
<PageLink pagename={this.props.pagename} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfilePic = React.createClass({
|
||||
var PagePic = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<img src={'https://graph.facebook.com/' + this.props.username + '/picture'} />
|
||||
<img src={'https://graph.facebook.com/' + this.props.pagename + '/picture'} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfileLink = React.createClass({
|
||||
var PageLink = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<a href={'https://www.facebook.com/' + this.props.username}>
|
||||
{this.props.username}
|
||||
<a href={'https://www.facebook.com/' + this.props.pagename}>
|
||||
{this.props.pagename}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<Avatar username="pwh" />,
|
||||
<Avatar pagename="Engineering" />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
## 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.
|
||||
In the above example, instances of `Avatar` *own* instances of `PagePic` and `PageLink`. 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.
|
||||
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`, `PagePic` and `PageLink` instances, and `div` is the **parent** (but not owner) of the `PagePic` and `PageLink` instances.
|
||||
|
||||
## Children
|
||||
|
||||
|
||||
@@ -8,59 +8,55 @@ next: reusable-components-zh-CN.html
|
||||
|
||||
目前为止,我们已经学了如何用单个组件来展示数据和处理用户输入。下一步让我们来体验 React 最激动人心的特性之一:可组合性(composability)。
|
||||
|
||||
|
||||
## 动机:关注分离
|
||||
|
||||
通过复用那些接口定义良好的组件来开发新的模块化组件,我们得到了与使用函数和类相似的好处。具体来说就是能够通过开发简单的组件把程序的*不同关注面分离*。如果为程序开发一套自定义的组件库,那么就能以最适合业务场景的方式来展示你的用户界面。
|
||||
|
||||
## 组合实例
|
||||
|
||||
一起来使用 Facebook Graph API 开发显示个人图片和用户名的简单 Avatar 组件吧。
|
||||
让我们用 Facebook Graph API 来开发一个显示 Facebook 页面图片和用户名的简单 Avatar 组件吧。
|
||||
|
||||
```javascript
|
||||
var Avatar = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ProfilePic username={this.props.username} />
|
||||
<ProfileLink username={this.props.username} />
|
||||
<PagePic pagename={this.props.pagename} />
|
||||
<PageLink pagename={this.props.pagename} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfilePic = React.createClass({
|
||||
var PagePic = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<img src={'https://graph.facebook.com/' + this.props.username + '/picture'} />
|
||||
<img src={'https://graph.facebook.com/' + this.props.pagename + '/picture'} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfileLink = React.createClass({
|
||||
var PageLink = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<a href={'https://www.facebook.com/' + this.props.username}>
|
||||
{this.props.username}
|
||||
<a href={'https://www.facebook.com/' + this.props.pagename}>
|
||||
{this.props.pagename}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<Avatar username="pwh" />,
|
||||
<Avatar pagename="Engineering" />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 从属关系
|
||||
|
||||
上面例子中,`Avatar` 拥有 `ProfilePic` 和 `ProfileLink` 的实例。`拥有者` 就是给其它组件设置 `props` 的那个组件。更正式地说,
|
||||
如果组件 `Y` 在 `render()` 方法是创建了组件 `X`,那么 `Y` 就拥有 `X`。上面讲过,组件不能修改自身的 `props` - 它们总是与它们拥有者设置的保持一致。这是保持用户界面一致性的基本不变量。
|
||||
|
||||
把从属关系与父子关系加以区别至关重要。从属关系是 React 特有的,而父子关系简单来讲就是DOM 里的标签的关系。在上一个例子中,`Avatar` 拥有 `div`、`ProfilePic` 和 `ProfileLink` 实例,`div` 是 `ProfilePic` 和 `ProfileLink` 实例的**父级**(但不是拥有者)。
|
||||
上面例子中,`Avatar` 拥有 `PagePic` 和 `PageLink` 的实例。`拥有者` 就是给其它组件设置 `props` 的那个组件。更正式地说,如果组件 `Y` 在 `render()` 方法是创建了组件 `X`,那么 `Y` 就拥有 `X`。上面讲过,组件不能修改自身的 `props` - 它们总是与它们拥有者设置的保持一致。这是保持用户界面一致性的基本不变量。
|
||||
|
||||
把从属关系与父子关系加以区别至关重要。从属关系是 React 特有的,而父子关系简单来讲就是DOM 里的标签的关系。在上一个例子中,`Avatar` 拥有 `div`、`PagePic` 和 `PageLink` 实例,`div` 是 `PagePic` 和 `PageLink` 实例的**父级**(但不是拥有者)。
|
||||
|
||||
## 子级
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
Oppure usando la nuova sintassi freccia di ES6:
|
||||
|
||||
```javascript
|
||||
var HelloMessage = (props) => <div>Ciao {props.name}</div>;
|
||||
const HelloMessage = (props) => <div>Ciao {props.name}</div>;
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
|
||||
@@ -244,7 +244,7 @@ ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
아니면 ES6의 화살표 문법을 사용할 수 있습니다.
|
||||
|
||||
```javascript
|
||||
var HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
const HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
|
||||
@@ -78,6 +78,27 @@ React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
### Single Child
|
||||
|
||||
With `React.PropTypes.element` you can specify that only a single child can be passed to a component as children.
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.children} // This must be exactly one element or it will warn.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
## Default Prop Values
|
||||
|
||||
React lets you define default values for your `props` in a very declarative way:
|
||||
@@ -115,28 +136,6 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
## Single Child
|
||||
|
||||
With `React.PropTypes.element` you can specify that only a single child can be passed to
|
||||
a component as children.
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.children} // This must be exactly one element or it will throw.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
## Mixins
|
||||
|
||||
Components are the best way to reuse code in React, but sometimes very different components may share some common functionality. These are sometimes called [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). React provides `mixins` to solve this problem.
|
||||
@@ -244,14 +243,15 @@ ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
Or using the new ES6 arrow syntax:
|
||||
|
||||
```javascript
|
||||
var HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
const 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.
|
||||
However, you may still specify `.propTypes` and `.defaultProps` by setting them as properties on the function, just as you would set them on an ES6 class.
|
||||
|
||||
> 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.
|
||||
In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.
|
||||
|
||||
@@ -8,7 +8,6 @@ next: transferring-props-zh-CN.html
|
||||
|
||||
设计接口的时候,把通用的设计元素(按钮,表单框,布局组件等)拆成接口良好定义的可复用的组件。这样,下次开发相同界面程序时就可以写更少的代码,也意义着更高的开发效率,更少的 Bug 和更少的程序体积。
|
||||
|
||||
|
||||
## Prop 验证
|
||||
|
||||
随着应用不断变大,保证组件被正确使用变得非常有用。为此我们引入 `propTypes`。`React.PropTypes` 提供很多验证器 (validator) 来验证传入数据的有效性。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。注意为了性能考虑,只在开发环境验证 `propTypes`。下面用例子来说明不同验证器的区别:
|
||||
@@ -32,10 +31,12 @@ React.createClass({
|
||||
// React 元素
|
||||
optionalElement: React.PropTypes.element,
|
||||
|
||||
// 你同样可以断言一个 prop 是一个类的实例。
|
||||
// 用 JS 的 instanceof 操作符声明 prop 为类的实例。
|
||||
optionalMessage: React.PropTypes.instanceOf(Message),
|
||||
|
||||
// 用 enum 来限制 prop 只接受指定的值。
|
||||
// 你可以用 enum 的方式
|
||||
// 确保你的 prop 被限定为指定值。
|
||||
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
|
||||
|
||||
// 指定的多个对象类型中的一个
|
||||
@@ -57,14 +58,16 @@ React.createClass({
|
||||
fontSize: React.PropTypes.number
|
||||
}),
|
||||
|
||||
// 以后任意类型加上 `isRequired` 来使 prop 不可空。
|
||||
// 你可以在任意东西后面加上 `isRequired`
|
||||
// 来确保 如果 prop 没有提供 就会显示一个警告。
|
||||
requiredFunc: React.PropTypes.func.isRequired,
|
||||
|
||||
// 不可空的任意类型
|
||||
requiredAny: React.PropTypes.any.isRequired,
|
||||
|
||||
// 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接
|
||||
// 使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
|
||||
// 你可以自定义一个验证器。如果验证失败需要返回一个 Error 对象。
|
||||
// 不要直接使用 `console.warn` 或抛异常,
|
||||
// 因为这在 `oneOfType` 里不起作用。
|
||||
customProp: function(props, propName, componentName) {
|
||||
if (!/matchme/.test(props[propName])) {
|
||||
return new Error('Validation failed!');
|
||||
@@ -75,6 +78,26 @@ React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
### Single Child
|
||||
|
||||
用 `React.PropTypes.element` 你可以指定仅有一个子级能被传送给组件
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.children} // 这里必须是一个元素否则就会警告
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
## 默认 Prop 值
|
||||
|
||||
@@ -93,9 +116,9 @@ var ComponentWithDefaultProps = React.createClass({
|
||||
|
||||
当父级没有传入 props 时,`getDefaultProps()` 可以保证 `this.props.value` 有默认值,注意 `getDefaultProps` 的结果会被 *缓存*。得益于此,你可以直接使用 props,而不必写手动编写一些重复或无意义的代码。
|
||||
|
||||
## 传递 Props:小技巧
|
||||
## 传递 Props:捷径
|
||||
|
||||
有一些常用的 React 组件只是对 HTML 做简单扩展。通常,你想少写点代码来把传入组件的 props 复制到对应的 HTML 元素上。这时 JSX 的 _spread_ 语法会帮到你:
|
||||
有一些常用的 React 组件只是对 HTML 做简单扩展。通常,你想 复制任何传进你的组件的HTML属性 到底层的HTML元素上。为了减少输入,你可以用 JSX _spread_ 语法来完成:
|
||||
|
||||
```javascript
|
||||
var CheckLink = React.createClass({
|
||||
@@ -113,28 +136,6 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
## 单个子级
|
||||
|
||||
`React.PropTypes.element` 可以限定只能有一个子级传入。
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.children} // 有且仅有一个元素,否则会抛异常。
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Mixins
|
||||
|
||||
组件是 React 里复用代码最佳方式,但是有时一些复杂的组件间也需要共用一些功能。有时会被称为 [跨切面关注点](https://en.wikipedia.org/wiki/Cross-cutting_concern)。React 使用 `mixins` 来解决这类问题。
|
||||
@@ -228,3 +229,29 @@ Counter.defaultProps = { initialCount: 0 };
|
||||
|
||||
不幸的是ES6的发布没有任何mixin的支持。因此,当你在ES6 classes下使用React时不支持mixins。作为替代,我们正在努力使它更容易支持这些用例不依靠mixins。
|
||||
|
||||
## 无状态函数
|
||||
|
||||
你也可以用 JavaScript 函数来定义你的 React 类。例如使用无状态函数语法:
|
||||
|
||||
```javascript
|
||||
function HelloMessage(props) {
|
||||
return <div>Hello {props.name}</div>;
|
||||
}
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
或者使用新的ES6箭头函数:
|
||||
|
||||
```javascript
|
||||
const HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
这个简化的组件API旨在用于那些纯函数态的组件 。这些组件必须没有保持任何内部状态,没有备份实例,也没有组件生命周期方法。他们纯粹的函数式的转化他们的输入,没有引用。
|
||||
然而,你仍然可以以设置为函数的properties的方式来指定 `.propTypes` 和 `.defaultProps`,就像你在ES6类里设置他们那样。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 因为无状态函数没有备份实例,你不能附加一个引用到一个无状态函数组件。 通常这不是问题,因为无状态函数不提供一个命令式的API。没有命令式的API,你就没有任何需要实例来做的事。然而,如果用户想查找无状态函数组件的DOM节点,他们必须把这个组件包装在一个有状态组件里(比如,ES6 类组件) 并且连接一个引用到有状态的包装组件。
|
||||
|
||||
在理想世界里,你的大多数组件都应该是无状态函数,因为将来我们可能会用避免不必要的检查和内存分配的方式来对这些组件进行优化。 如果可能,这是推荐的模式。
|
||||
|
||||
@@ -27,16 +27,14 @@ Nel resto di questo tutorial vengono illustrate le best practices, usando JSX e
|
||||
Nella maggior parte dei casi dovresti esplicitamente passare le proprietà. Ciò assicura che venga esposto soltanto un sottoinsieme dell'API interna, del cui funzionamento si è certi.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Ciao mondo!
|
||||
@@ -58,22 +56,20 @@ A volte passare manualmente ciascuna proprietà può essere noioso e fragile. In
|
||||
Elenca tutte le proprietà che desideri consumare, seguite da `...other`.
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
var { checked, ...other } = props;
|
||||
```
|
||||
|
||||
Ciò assicura che vengano passate tutte le proprietà TRANNE quelle che stai consumando tu stesso.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` contiene { onClick: console.log } ma non la proprietà checked
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` contiene { onClick: console.log } ma non la proprietà checked
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Ciao mondo!
|
||||
@@ -89,15 +85,13 @@ ReactDOM.render(
|
||||
Usa sempre il pattern di destrutturazione quando trasferisci altre proprietà sconosciute in `other`.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// ANTI-PATTERN: `checked` sarebbe passato al componente interno
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// ANTI-PATTERN: `checked` sarebbe passato al componente interno
|
||||
return (
|
||||
<div {...props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Consumare e Trasferire la Stessa Proprietà
|
||||
@@ -105,23 +99,21 @@ var FancyCheckbox = React.createClass({
|
||||
Se il tuo componente desidera consumare una proprietà, ma anche passarla ad altri, puoi passarla esplicitamente mediante `checked={checked}`. Questo è preferibile a passare l'intero oggetto `this.props` dal momento che è più facile effettuarne il linting e il refactoring.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, title, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> NOTA:
|
||||
@@ -150,14 +142,12 @@ z; // { a: 3, b: 4 }
|
||||
Se non usi JSX, puoi usare una libreria per ottenere il medesimo pattern. Underscore supporta `_.omit` per omettere delle proprietà ed `_.extend` per copiare le proprietà in un nuovo oggetto.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var checked = props.checked;
|
||||
var other = _.omit(props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -29,16 +29,14 @@ React.createElement(Component, Object.assign({}, this.props, { more: 'values' })
|
||||
ほとんどの場合、プロパティを明確に子要素に渡すべきです。それは、内部のAPIのサブセットだけを外に出していることと、認識しているプロパティが動作することを保証します。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -59,22 +57,20 @@ ReactDOM.render(
|
||||
以下のように `...other` を使うことで、使いたいプロパティを一覧にすることができます。
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
var { checked, ...other } = props;
|
||||
```
|
||||
|
||||
これは、自分で指定したものは 除き 、全てのpropsを渡すことを保証します。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` は { onClick: console.log } を含みますが、 checked プロパティは含みません。
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` は { onClick: console.log } を含みますが、 checked プロパティは含みません。
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -89,15 +85,13 @@ ReactDOM.render(
|
||||
未知の `other` propsを移譲する際には、分割代入パターンを常に使ってください。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// アンチパターン: `checked` が内部のコンポーネントに渡されます。
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// アンチパターン: `checked` が内部のコンポーネントに渡されます。
|
||||
return (
|
||||
<div {...props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 同じpropを使い、移譲する
|
||||
@@ -105,23 +99,21 @@ var FancyCheckbox = React.createClass({
|
||||
コンポーネントがプロパティを使うだけでなく、子要素に渡したい場合は、明確に `checked={checked}` と記述することで再度渡すことができます。 `this.props` オブジェクトで全てを渡すほうが、リファクタリングやチェックをしやすいので好ましいです。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, title, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> 注意:
|
||||
@@ -148,14 +140,12 @@ z; // { a: 3, b: 4 }
|
||||
JSXを使わない際には、同じパターンを行うライブラリを使うことができます。Underscoreでは、 `_.omit` を使ってプロパティをフィルタしたり、 `_.extend` を使って新しいオブジェクトにプロパティをコピーしたりできます。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var checked = props.checked;
|
||||
var other = _.omit(props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -27,16 +27,14 @@ React.createElement(Component, Object.assign({}, this.props, { more: 'values' })
|
||||
대부분의 경우 명시적으로 프로퍼티를 아래로 전달해야 합니다. 이는 동작을 확신하는 내부 API의 일부만 공개하도록 합니다.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
세상아 안녕!
|
||||
@@ -59,22 +57,20 @@ ReactDOM.render(
|
||||
소비할 프로퍼티들을 나열하고, 그 뒤에 `...other`를 넣습니다.
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
var { checked, ...other } = props;
|
||||
```
|
||||
|
||||
이는 지금 소비한 props를 *제외한* 나머지를 아래로 전달합니다.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other`에는 { onClick: console.log }가 포함되지만 checked 프로퍼티는 제외됩니다
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other`에는 { onClick: console.log }가 포함되지만 checked 프로퍼티는 제외됩니다
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
세상아 안녕!
|
||||
@@ -90,15 +86,13 @@ ReactDOM.render(
|
||||
미상의 `other` props을 전달할 때는 항상 구조 해체 패턴을 사용하세요.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// 반례: `checked` 또한 내부 컴포넌트로 전달될 것입니다
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// 반례: `checked` 또한 내부 컴포넌트로 전달될 것입니다
|
||||
return (
|
||||
<div {...props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 같은 Prop을 소비하고 전달하기
|
||||
@@ -106,23 +100,21 @@ var FancyCheckbox = React.createClass({
|
||||
컴포넌트가 프로퍼티를 사용하지만 계속 넘기길 원한다면, `checked={checked}`처럼 명시적으로 다시 넘길 수 있습니다. 리팩토링과 린트(lint)하기가 더 쉬우므로 이 방식이 `this.props` 객체 전부를 넘기는 것보다 낫습니다.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, title, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> 주의:
|
||||
@@ -152,14 +144,12 @@ z; // { a: 3, b: 4 }
|
||||
JSX를 사용하지 않는다면 라이브러리를 사용해 같은 패턴을 쓸 수 있습니다. Underscore에서는 `_.omit`을 사용해 특정 프로퍼티를 제외하거나 `_.extend`를 사용해 새로운 객체로 프로퍼티를 복사할 수 있습니다.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var checked = props.checked;
|
||||
var other = _.omit(props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -20,23 +20,21 @@ If you don't use JSX, you can use any object helper such as ES6 `Object.assign`
|
||||
React.createElement(Component, Object.assign({}, this.props, { more: 'values' }));
|
||||
```
|
||||
|
||||
The rest of this tutorial explains best practices. It uses JSX and experimental ES7 syntax.
|
||||
The rest of this tutorial explains best practices. It uses JSX and experimental ECMAScript syntax.
|
||||
|
||||
## Manual Transfer
|
||||
|
||||
Most of the time you should explicitly pass the properties down. This ensures that you only expose a subset of the inner API, one that you know will work.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -58,22 +56,20 @@ Sometimes it's fragile and tedious to pass every property along. In that case yo
|
||||
List out all the properties that you would like to consume, followed by `...other`.
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
var { checked, ...other } = props;
|
||||
```
|
||||
|
||||
This ensures that you pass down all the props EXCEPT the ones you're consuming yourself.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` contains { onClick: console.log } but not the checked property
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` contains { onClick: console.log } but not the checked property
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -89,39 +85,35 @@ ReactDOM.render(
|
||||
Always use the destructuring pattern when transferring unknown `other` props.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// ANTI-PATTERN: `checked` would be passed down to the inner component
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// ANTI-PATTERN: `checked` would be passed down to the inner component
|
||||
return (
|
||||
<div {...props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Consuming and Transferring the Same Prop
|
||||
|
||||
If your component wants to consume a property but also wants to pass it along, you can repass it explicitly with `checked={checked}`. This is preferable to passing the full `this.props` object since it's easier to refactor and lint.
|
||||
If your component wants to consume a property but also wants to pass it along, you can repass it explicitly with `checked={checked}`. This is preferable to passing the full `props` object since it's easier to refactor and lint.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, title, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> NOTE:
|
||||
@@ -132,7 +124,7 @@ var FancyCheckbox = React.createClass({
|
||||
|
||||
Rest properties allow you to extract the remaining properties from an object into a new object. It excludes every other property listed in the destructuring pattern.
|
||||
|
||||
This is an experimental implementation of an [ES7 proposal](https://github.com/sebmarkbage/ecmascript-rest-spread).
|
||||
This is an experimental implementation of an [ECMAScript proposal](https://github.com/sebmarkbage/ecmascript-rest-spread).
|
||||
|
||||
```javascript
|
||||
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
|
||||
@@ -143,21 +135,19 @@ z; // { a: 3, b: 4 }
|
||||
|
||||
> Note:
|
||||
>
|
||||
> This proposal has reached stage 2 and is now enabled by default in Babel. Older versions of Babel may need to explicitly enable this transform with `babel --optional es7.objectRestSpread`
|
||||
> To transform rest and spread properties using Babel 6, you need to install the [`es2015`](https://babeljs.io/docs/plugins/preset-es2015/) preset, the [`transform-object-rest-spread`](https://babeljs.io/docs/plugins/transform-object-rest-spread/) plugin and configure them in the `.babelrc` file.
|
||||
|
||||
## Transferring with Underscore
|
||||
|
||||
If you don't use JSX, you can use a library to achieve the same pattern. Underscore supports `_.omit` to filter out properties and `_.extend` to copy properties onto a new object.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var checked = props.checked;
|
||||
var other = _.omit(props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -20,23 +20,21 @@ React 里有一个非常常用的模式就是对组件做一层抽象。组件
|
||||
React.createElement(Component, Object.assign({}, this.props, { more: 'values' }));
|
||||
```
|
||||
|
||||
下面的教程介绍一些最佳实践。使用了 JSX 和 ES7 的还在试验阶段的特性。
|
||||
下面的教程介绍一些最佳实践。使用了 JSX 和 试验性的ECMAScript 语法。
|
||||
|
||||
## 手动传递
|
||||
|
||||
大部分情况下你应该显式地向下传递 props。这样可以确保只公开你认为是安全的内部 API 的子集。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -58,22 +56,20 @@ ReactDOM.render(
|
||||
列出所有要当前使用的属性,后面跟着 `...other`。
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
var { checked, ...other } = props;
|
||||
```
|
||||
|
||||
这样能确保把所有 props 传下去,*除了* 那些已经被使用了的。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` 包含 { onClick: console.log } 但 checked 属性除外
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` 包含 { onClick: console.log } 但 checked 属性除外
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -89,52 +85,46 @@ ReactDOM.render(
|
||||
在传递这些未知的 `other` 属性时,要经常使用解构赋值模式。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// 反模式:`checked` 会被传到里面的组件里
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// 反模式:`checked` 会被传到里面的组件里
|
||||
return (
|
||||
<div {...props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 使用和传递同一个 Prop
|
||||
|
||||
如果组件需要使用一个属性又要往下传递,可以直接使用 `checked={checked}` 再传一次。这样做比传整个 `this.props` 对象要好,因为更利于重构和语法检查。
|
||||
如果组件需要使用一个属性又要往下传递,可以直接使用 `checked={checked}` 再传一次。这样做比传整个 `props` 对象要好,因为更利于重构和语法检查。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, title, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 顺序很重要,把 `{...other}` 放到 JSX props 前面会使它不被覆盖。上面例子中我们可以保证 input 的 type 是 `"checkbox"`。
|
||||
|
||||
|
||||
## 剩余属性和展开属性 `...`
|
||||
|
||||
剩余属性可以把对象剩下的属性提取到一个新的对象。会把所有在解构赋值中列出的属性剔除。
|
||||
|
||||
这是 [ES7 草案](https://github.com/sebmarkbage/ecmascript-rest-spread) 中的试验特性。
|
||||
这是 [ECMAScript 草案](https://github.com/sebmarkbage/ecmascript-rest-spread) 中的试验特性。
|
||||
|
||||
```javascript
|
||||
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
|
||||
@@ -145,22 +135,19 @@ z; // { a: 3, b: 4 }
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 使用 [JSX 命令行工具](https://www.npmjs.com/package/react-tools) 配合 `--harmony` 标记来启用 ES7 语法。
|
||||
|
||||
> 要用 Babel 6转换 rest 和 spread 属性,你需要安装 [`es2015`](https://babeljs.io/docs/plugins/preset-es2015/) preset,[`transform-object-rest-spread`](https://babeljs.io/docs/plugins/transform-object-rest-spread/) 插件并在 `.babelrc` 里配置他们.
|
||||
|
||||
## 使用 Underscore 来传递
|
||||
|
||||
如果不使用 JSX,可以使用一些库来实现相同效果。Underscore 提供 `_.omit` 来过滤属性,`_.extend` 复制属性到新的对象。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var checked = props.checked;
|
||||
var other = _.omit(props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -34,7 +34,7 @@ Like all DOM events, the `onChange` prop is supported on all native components a
|
||||
|
||||
## 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:
|
||||
A **controlled** `<input>` has a `value` prop. Rendering a controlled `<input>` will reflect the value of the `value` prop.
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
@@ -42,7 +42,7 @@ An `<input>` with `value` set is a *controlled* component. In a controlled `<inp
|
||||
}
|
||||
```
|
||||
|
||||
This will render an input that always has a value of `Hello!`. Any user input will have no effect on the rendered element because React has declared the value to be `Hello!`. If you wanted to update the value in response to user input, you could use the `onChange` event:
|
||||
User input will have no effect on the rendered element because React has declared the value to be `Hello!`. To update the value in response to user input, you could use the `onChange` event:
|
||||
|
||||
```javascript
|
||||
getInitialState: function() {
|
||||
@@ -52,12 +52,17 @@ This will render an input that always has a value of `Hello!`. Any user input wi
|
||||
this.setState({value: event.target.value});
|
||||
},
|
||||
render: function() {
|
||||
var value = this.state.value;
|
||||
return <input type="text" value={value} onChange={this.handleChange} />;
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
value={this.state.value}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
In this example, we are simply accepting the newest value provided by the user and updating the `value` prop of the `<input>` component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. For example:
|
||||
In this example, we are accepting the value provided by the user and updating the `value` prop of the `<input>` component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. For example:
|
||||
|
||||
```javascript
|
||||
handleChange: function(event) {
|
||||
@@ -65,7 +70,9 @@ In this example, we are simply accepting the newest value provided by the user a
|
||||
}
|
||||
```
|
||||
|
||||
This would accept user input but truncate the value to the first 140 characters.
|
||||
This would accept user input and truncate the value to the first 140 characters.
|
||||
|
||||
A **Controlled** component does not maintain its own internal state; the component renders purely based on props.
|
||||
|
||||
### Potential Issues With Checkboxes and Radio Buttons
|
||||
|
||||
@@ -73,7 +80,7 @@ Be aware that, in an attempt to normalize change handling for checkbox and radio
|
||||
|
||||
## Uncontrolled Components
|
||||
|
||||
An `<input>` that does not supply a `value` (or sets it to `null`) is an *uncontrolled* component. In an uncontrolled `<input>`, the value of the rendered element will reflect the user's input. For example:
|
||||
An `<input>` without a `value` property is an *uncontrolled* component:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
@@ -83,6 +90,8 @@ An `<input>` that does not supply a `value` (or sets it to `null`) is an *uncont
|
||||
|
||||
This will render an input that starts off with an empty value. Any user input will be immediately reflected by the rendered element. If you wanted to listen to updates to the value, you could use the `onChange` event just like you can with controlled components.
|
||||
|
||||
An **uncontrolled** component maintains its own internal state.
|
||||
|
||||
### Default Value
|
||||
|
||||
If you want to initialize the component with a non-empty value, you can supply a `defaultValue` prop. For example:
|
||||
@@ -95,7 +104,7 @@ If you want to initialize the component with a non-empty value, you can supply a
|
||||
|
||||
This example will function much like the **Uncontrolled Components** example above.
|
||||
|
||||
Likewise, `<input>` supports `defaultChecked` and `<select>` supports `defaultValue`.
|
||||
Likewise, `<input type="checkbox">` and `<input type="radio">` support `defaultChecked`, and `<select>` supports `defaultValue`.
|
||||
|
||||
> Note:
|
||||
>
|
||||
|
||||
@@ -30,12 +30,11 @@ next: working-with-the-browser-zh-CN.html
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 对于 `<input>` and `<textarea>`, `onChange` 替代 — 一般应该用来替代 — the DOM's 内建的 [`oninput`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput) 事件处理。
|
||||
> 对于 `<input>` and `<textarea>`, `onChange` 取代 — 一般应该用来替代 — DOM内建的 [`oninput`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput) 事件处理。
|
||||
|
||||
## 受控组件
|
||||
|
||||
## 受限组件
|
||||
|
||||
设置了 `value` 的 `<input>` 是一个*受限*组件。 对于受限的 `<input>`,渲染出来的 HTML 元素始终保持 `value` 属性的值。例如:
|
||||
一个*受控*的 `<input>` 有一个 `value` prop。渲染一个受控 `<input>` 会反映 `value` prop 的值。
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
@@ -43,7 +42,7 @@ next: working-with-the-browser-zh-CN.html
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码将渲染出一个值为 `Hello!` 的 input 元素。用户在渲染出来的元素里输入任何值都不起作用,因为 React 已经赋值为 `Hello!`。如果想响应更新用户输入的值,就得使用 `onChange` 事件:
|
||||
用户输入在被渲染的元素里将没有作用,因为 React 已经声明值为 `Hello!`。要更新 value 来响应用户输入,你可以使用 `onChange` 事件:
|
||||
|
||||
```javascript
|
||||
getInitialState: function() {
|
||||
@@ -53,12 +52,17 @@ next: working-with-the-browser-zh-CN.html
|
||||
this.setState({value: event.target.value});
|
||||
},
|
||||
render: function() {
|
||||
var value = this.state.value;
|
||||
return <input type="text" value={value} onChange={this.handleChange} />;
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
value={this.state.value}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码中,React 将用户输入的值更新到 `<input>` 组件的 `value` 属性。这样实现响应或者验证用户输入的界面就很容易了。例如:
|
||||
在这个例子中,我们接受用户提供的值并更新 `<input>` 组件的 `value` prop。这个模式使实现响应或者验证用户输入的界面更容易。例如:
|
||||
|
||||
```javascript
|
||||
handleChange: function(event) {
|
||||
@@ -68,14 +72,15 @@ next: working-with-the-browser-zh-CN.html
|
||||
|
||||
上面的代码接受用户输入,并截取前 140 个字符。
|
||||
|
||||
受控组件不维持一个自己的内部状态;它单纯的基于 props 渲染。
|
||||
|
||||
### 复选框与单选按钮的潜在问题
|
||||
|
||||
当心,在力图标准化复选框与单选按钮的变换处理中,React使用`click` 事件代替 `change` 事件。在大多数情况下它们表现的如同预期,除了在`change` handler中调用`preventDefault` 。`preventDefault` 阻止了浏览器视觉上更新输入,即使`checked`被触发。变通的方式是要么移除`preventDefault`的调用,要么把`checked` 的触发放在一个`setTimeout`里。
|
||||
|
||||
## 不受控组件
|
||||
|
||||
## 不受限组件
|
||||
|
||||
没有设置 `value`(或者设为 `null`) 的 `<input>` 组件是一个*不受限*组件。对于不受限的 `<input>` 组件,渲染出来的元素直接反应用户输入。例如:
|
||||
一个没有 `value` 属性的 `<input>` 是一个不*受控*组件:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
@@ -83,7 +88,9 @@ next: working-with-the-browser-zh-CN.html
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码将渲染出一个空值的输入框,用户输入将立即反应到元素上。和受限元素一样,使用 `onChange` 事件可以监听值的变化。
|
||||
上面的代码将渲染出一个空值的输入框,用户输入将立即反应到元素上。和受控元素一样,使用 `onChange` 事件可以监听值的变化。
|
||||
|
||||
*不受控*组件维持它自己的内部状态。
|
||||
|
||||
### 默认值
|
||||
|
||||
@@ -95,19 +102,17 @@ next: working-with-the-browser-zh-CN.html
|
||||
}
|
||||
```
|
||||
|
||||
这个例子会像上面的**Controlled Components** 例子一样运行。
|
||||
这个例子会像上面的 **不受控组件** 例子一样运行。
|
||||
|
||||
同样的, `<input>` 支持 `defaultChecked` 、 `<select>` 支持 `defaultValue`.
|
||||
同样的, `<input type="checkbox">` 和 `<input type="radio">` 支持 `defaultChecked` 、 `<select>` 支持 `defaultValue`.
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> `defaultValue` 和 `defaultChecked` props 只能在内部渲染时被使用。 如果你需要在随后的渲染更新值, 你需要使用 [受限组件](#受限组件).
|
||||
|
||||
> `defaultValue` 和 `defaultChecked` props 只能在内部渲染时被使用。 如果你需要在随后的渲染更新值, 你需要使用 [受控组件](#受控组件).
|
||||
|
||||
## 高级主题
|
||||
|
||||
|
||||
### 为什么使用受限组件?
|
||||
### 为什么使用受控组件?
|
||||
|
||||
在 React 中使用诸如 `<input>` 的表单组件时,遇到了一个在传统 HTML 中没有的挑战。比如下面的代码:
|
||||
|
||||
@@ -115,9 +120,9 @@ next: working-with-the-browser-zh-CN.html
|
||||
<input type="text" name="title" value="Untitled" />
|
||||
```
|
||||
|
||||
在 HTML 中将渲染 *初始值* 为 `Untitled` 的输入框。用户改变输入框的值时,节点的 `value` 属性( *property*)将随之变化,但是 `node.getAttribute('value')` 还是会返回初始设置的值 `Untitled`.
|
||||
它渲染一个*初始值*为 `Untitled` 的输入框。当用户改变输入框的值时,节点的 `value` 属性( *property*)将随之变化,但是 `node.getAttribute('value')` 还是会返回初始设置的值 `Untitled`.
|
||||
|
||||
与 HTML 不同,React 组件必须在任何时间点描绘视图的状态,而不仅仅是在初始化时。比如在 React 中:
|
||||
与 HTML 不同,React 组件必须在任何时间点表现视图的状态,而不仅仅是在初始化时。比如在 React 中:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
@@ -125,8 +130,7 @@ next: working-with-the-browser-zh-CN.html
|
||||
}
|
||||
```
|
||||
|
||||
该方法在任何时间点渲染组件以后,输入框的值就应该 *始终* 为 `Untitled`。
|
||||
|
||||
既然这个方法描述了在任意时间点上的视图,那么文本输入框的值就应该*始终*为 `Untitled`。
|
||||
|
||||
### 为什么 `<textarea>` 使用 `value` 属性?
|
||||
|
||||
@@ -137,7 +141,7 @@ next: working-with-the-browser-zh-CN.html
|
||||
<textarea name="description">This is the description.</textarea>
|
||||
```
|
||||
|
||||
对 HTML 而言,让开发者设置多行的值很容易。但是,React 是 JavaScript,没有字符限制,可以使用 `\n` 实现换行。简言之,React 已经有 `value`、`defaultValue` 属性,`</textarea>` 组件的子节点扮演什么角色就有点模棱两可了。基于此, 设置 `<textarea>` 值时不应该使用子节点:
|
||||
对 HTML 而言,让开发者设置多行的值很容易。但是,React 是 JavaScript,没有字符串限制,可以使用 `\n` 实现换行。简言之,React 已经有 `value`、`defaultValue` 属性,`</textarea>` 组件的子节点扮演什么角色就有点模棱两可了。基于此, 设置 `<textarea>` 值时不应该使用子节点:
|
||||
|
||||
```javascript
|
||||
<textarea name="description" value="This is a description." />
|
||||
@@ -145,7 +149,6 @@ next: working-with-the-browser-zh-CN.html
|
||||
|
||||
如果 *非要* 使用子节点,效果和使用 `defaultValue` 一样。
|
||||
|
||||
|
||||
### 为什么 `<select>` 使用 `value` 属性
|
||||
|
||||
HTML 中 `<select>` 通常使用 `<option>` 的 `selected` 属性设置选中状态;React 为了更方面的控制组件,采用以下方式代替:
|
||||
@@ -158,7 +161,7 @@ HTML 中 `<select>` 通常使用 `<option>` 的 `selected` 属性设置选中状
|
||||
</select>
|
||||
```
|
||||
|
||||
如果是不受限组件,则使用 `defaultValue`。
|
||||
如果是不受控组件,则使用 `defaultValue`。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
|
||||
@@ -12,7 +12,7 @@ React provides powerful abstractions that free you from touching the DOM directl
|
||||
|
||||
React is very fast because it never talks to the DOM directly. React maintains a fast in-memory representation of the DOM. `render()` methods actually return a *description* of the DOM, and React can compare this description with the in-memory representation to compute the fastest way to update the browser.
|
||||
|
||||
Additionally, React implements a full synthetic event system such that all event objects are guaranteed to conform to the W3C spec despite browser quirks, and everything bubbles consistently and efficiently across browsers. You can even use some HTML5 events in IE8!
|
||||
Additionally, React implements a full synthetic event system such that all event objects are guaranteed to conform to the W3C spec despite browser quirks, and everything bubbles consistently and efficiently across browsers. You can even use some HTML5 events in older browsers that don't ordinarily support them!
|
||||
|
||||
Most of the time you should stay within React's "faked browser" world since it's more performant and easier to reason about. However, sometimes you simply need to access the underlying API, perhaps to work with a third-party library like a jQuery plugin. React provides escape hatches for you to use the underlying DOM API directly.
|
||||
|
||||
@@ -53,45 +53,8 @@ _Mounted_ composite components also support the following method:
|
||||
|
||||
* `component.forceUpdate()` can be invoked on any mounted component when you know that some deeper aspect of the component's state has changed without using `this.setState()`.
|
||||
|
||||
## Browser Support and Polyfills
|
||||
## Browser Support
|
||||
|
||||
At Facebook, we support older browsers, including IE8. We've had polyfills in place for a long time to allow us to write forward-thinking JS. This means we don't have a bunch of hacks scattered throughout our codebase and we can still expect our code to "just work". For example, instead of seeing `+new Date()`, we can just write `Date.now()`. Since the open source React is the same as what we use internally, we've carried over this philosophy of using forward thinking JS.
|
||||
React supports most popular browsers, including Internet Explorer 9 and above.
|
||||
|
||||
In addition to that philosophy, we've also taken the stance that we, as authors of a JS library, should not be shipping polyfills as a part of our library. If every library did this, there's a good chance you'd be sending down the same polyfill multiple times, which could be a sizable chunk of dead code. If your product needs to support older browsers, chances are you're already using something like [es5-shim](https://github.com/es-shims/es5-shim).
|
||||
|
||||
### Polyfills Needed to Support Older Browsers
|
||||
|
||||
`es5-shim.js` from [kriskowal's es5-shim](https://github.com/es-shims/es5-shim) provides the following that React needs:
|
||||
|
||||
* `Array.isArray`
|
||||
* `Array.prototype.every`
|
||||
* `Array.prototype.forEach`
|
||||
* `Array.prototype.indexOf`
|
||||
* `Array.prototype.map`
|
||||
* `Date.now`
|
||||
* `Function.prototype.bind`
|
||||
* `Object.keys`
|
||||
* `String.prototype.split`
|
||||
* `String.prototype.trim`
|
||||
|
||||
`es5-sham.js`, also from [kriskowal's es5-shim](https://github.com/es-shims/es5-shim), provides the following that React needs:
|
||||
|
||||
* `Object.create`
|
||||
* `Object.freeze`
|
||||
|
||||
The unminified build of React needs the following from [paulmillr's console-polyfill](https://github.com/paulmillr/console-polyfill).
|
||||
|
||||
* `console.*`
|
||||
|
||||
When using HTML5 elements in IE8 including `<section>`, `<article>`, `<nav>`, `<header>`, and `<footer>`, it's also necessary to include [html5shiv](https://github.com/aFarkas/html5shiv) or a similar script.
|
||||
|
||||
### Cross-browser Issues
|
||||
|
||||
Although React is pretty good at abstracting browser differences, some browsers are limited or present quirky behaviors that we couldn't find a workaround for.
|
||||
|
||||
#### onScroll event on IE8
|
||||
|
||||
On IE8 the `onScroll` event doesn't bubble and IE8 doesn't have an API to define handlers to the capturing phase of an event, meaning there is no way for React to listen to these events.
|
||||
Currently a handler to this event is ignored on IE8.
|
||||
|
||||
See the [onScroll doesn't work in IE8](https://github.com/facebook/react/issues/631) GitHub issue for more information.
|
||||
(We don't support older browsers that don't support ES5 methods, but you may find that your apps do work in older browsers if polyfills such as [es5-shim and es5-sham](https://github.com/es-shims/es5-shim) are included in the page. You're on your own if you choose to take this path.)
|
||||
|
||||
@@ -8,59 +8,17 @@ next: more-about-refs-zh-CN.html
|
||||
|
||||
React提供了强大的抽象机制使你在大多数情况下免于直接接触DOM,但有时你仅仅只需要访问底层API,也许是为了与第三方库或者已有的代码协作。
|
||||
|
||||
|
||||
## 虚拟DOM
|
||||
|
||||
React如此快速是因为它从不直接操作DOM。React维持了一个快速的内存中的DOM表示。`render()` 方法返回一个DOM的*描述*,然后React能根据内存中的描述diff此描述来计算出最快速的方法更新浏览器。
|
||||
React非常快速是因为它从不直接操作DOM。React维持了一个快速的内存中的DOM表示。`render()` 方法实际上返回一个对DOM的*描述*,然后React能根据内存中的“描述”来比较此“描述”以计算出最快速的方法更新浏览器。
|
||||
|
||||
此外,React实现了一个完备的合成事件(synthetic event)系统,以使得所有的事件对象都被保证符合W3C细则,而不论各个浏览器的怪癖,并且所有事件跨浏览器地一致并高效的冒泡(bubbles),你甚至能在IE8里使用一些HTML5事件!
|
||||
|
||||
大多数时间你应该和React的"伪造浏览器"呆在一起,因为它更高性能并且容易推理。然而,有时你只需要访问底层API,或许是为了与第三方库比如一个jQuery插件协作。React为你提供了安全仓口来直接使用底层API。
|
||||
|
||||
|
||||
## Refs 和 findDOMNode()
|
||||
|
||||
为了与浏览器互动,你需要一个指向DOM node的引用。React有一个函数`ReactDOM.findDOMNode(component)` ,你能调用以得到一个指向指向组件的DOM node的引用。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> `findDOMNode()` 只作用于已挂载的组件(即,已经放置于DOM中的组件)。如果你尝试在还没有被挂载的组件上调用此函数(比如在`render()` 里有待被创建的组件上调用`findDOMNode()`将会抛出一个异常)
|
||||
|
||||
为了获得一个指向React组件的引用,你可以要么使用`this` 来得到当前React组件,要么使用refs来引用你拥有的组件。它们像这样工作:
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// 明确的强制text input使用原生DOM API。
|
||||
ReactDOM.findDOMNode(this.refs.myTextInput).focus();
|
||||
},
|
||||
render: function() {
|
||||
// 当组件被挂载时
|
||||
// ref属性给this.refs添加了一个指向指向组件的引用
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref="myTextInput" />
|
||||
<input
|
||||
type="button"
|
||||
value="Focus the text input"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<MyComponent />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 更多关于Refs
|
||||
|
||||
要学习更多有关refs,包括更有效使用它们的方法,请参见[more about refs](/react/docs/more-about-refs.html) 文档。
|
||||
|
||||
为了与浏览器互动,你需要一个指向DOM node的引用。你可以连接一个 `ref` 到任何的元素,这允许你引用 组件的 **backing instance** 。它很有用,如果你需要在组件上调用命令式函数,或者想访问底层的DOM节点。要了解很多关于 refs,包括更有效使用他们的方法,请查看我们的 [关于Refs的更多内容](/react/docs/more-about-refs-zh-CN.html) 文档。
|
||||
|
||||
## 组件的生命周期
|
||||
|
||||
@@ -72,14 +30,12 @@ ReactDOM.render(
|
||||
|
||||
React提供生命周期方法,以便你可以指定钩挂到这个过程上。我们提供了 **will** 方法,该方法在某事发生前被调用,**did**方法,在某事发生后被调用。
|
||||
|
||||
|
||||
### 挂载
|
||||
|
||||
* `getInitialState(): object` 在组件挂载前被调用. 有状态组件(Stateful components) 应该实现此函数并返回初始state的数据。
|
||||
* `componentWillMount()` 在挂载发生前被立即调用。
|
||||
* `componentDidMount()` 在挂载发生后被立即调用。 需要DOM node的初始化应该放在这里。
|
||||
|
||||
|
||||
### 更新
|
||||
|
||||
* `componentWillReceiveProps(object nextProps)` 当挂载的组件接收到新的props时被调用。此方法应该被用于比较`this.props` 和 `nextProps`以用于使用`this.setState()`执行状态转换。
|
||||
@@ -87,19 +43,15 @@ React提供生命周期方法,以便你可以指定钩挂到这个过程上。
|
||||
* `componentWillUpdate(object nextProps, object nextState)` 在更新发生前被立即调用。你不能在此调用`this.setState()`。
|
||||
* `componentDidUpdate(object prevProps, object prevState)` 在更新发生后被立即调用。
|
||||
|
||||
|
||||
### 卸载
|
||||
|
||||
* `componentWillUnmount()` 在组件被卸载和摧毁后被立即调用。清理应该放在这里。
|
||||
|
||||
|
||||
### Mounted Methods
|
||||
### 已挂载的方法
|
||||
|
||||
_Mounted_ 复合组件同样支持以下方法:
|
||||
|
||||
* `findDOMNode(): DOMElement` 能够在任何已挂载的组件上调用以便于获取指向它渲染的DOM node的引用。
|
||||
* `forceUpdate()` 能在任何已挂载的组件上调用,当你知道一些更深层次的组件状态变化了但没有使用 `this.setState()`。
|
||||
|
||||
* `component.forceUpdate()` 可以在任何已挂载的组件上调用,在你知道 某些深处的组件状态被未使用 `this.setState()` 改变了时。
|
||||
|
||||
## 浏览器支持和填充物(polyfills)
|
||||
|
||||
@@ -107,7 +59,6 @@ _Mounted_ 复合组件同样支持以下方法:
|
||||
|
||||
除了这种哲学外,我们也采用了这样的立场,我们,作为一个JS库的作者,不应该把polyfills作为我们库的一部分。如果所有的库这样做,就有很大的机会发送同样的polyfill多次,这可能是一个相当大的无用代码。如果你的产品需要支援老的浏览器,你很有可能已经在使用某些东西比如[es5-shim](https://github.com/es-shims/es5-shim)。
|
||||
|
||||
|
||||
### 需要用来支持旧浏览器的Polyfills
|
||||
|
||||
来自 [kriskowal's es5-shim](https://github.com/es-shims/es5-shim)的`es5-shim.js` 提供了如下React需要的东西:
|
||||
@@ -134,12 +85,10 @@ _Mounted_ 复合组件同样支持以下方法:
|
||||
|
||||
当在IE8里使用HTML5元素,包括`<section>`, `<article>`, `<nav>`, `<header>`, 和 `<footer>`, 同样必须包含[html5shiv](https://github.com/aFarkas/html5shiv) 或者类似的脚本。
|
||||
|
||||
|
||||
### 跨浏览器问题
|
||||
|
||||
尽管React在抽象浏览器不同时做的相当好,但一些浏览器被限制或者表现出怪异的行为,我们没能找到变通的方案解决。
|
||||
|
||||
|
||||
#### IE8的onScroll事件
|
||||
|
||||
在IE8`onScroll` 事件不冒泡,并且IE8没有定义事件捕获阶段handlers的API,意味React这没有办法去监听这些事件。
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
---
|
||||
id: more-about-refs
|
||||
title: Refs 的更多信息
|
||||
permalink: more-about-refs-zh-CN.html
|
||||
prev: working-with-the-browser-zh-CN.html
|
||||
next: tooling-integration-zh-CN.html
|
||||
---
|
||||
在从render方法返回你的UI结构之前,你可能想向从`render()` 返回的组件的实例“伸手”并调用其上的方法。通常,做类似这样的事情没必要在你的引用中制造数据流,因为Reactive的数据量确保最近的`props` 被发送到从 `render()` 返回的每个孩子中。然而,有些情况,这样做还是必须的或者有帮助的。
|
||||
|
||||
考虑一下情形,元素`<input />` (他存在于你的子层级中),当你更新它的值为一个空的字符串`''` 的时候,你告诉它获得焦点。
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
this.setState({userInput: ''}); //清空输入
|
||||
// 现在我们希望获取焦点<input />!
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
Click to Focus and Reset
|
||||
</div>
|
||||
<input
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
在这个例子中,注意我们是如何想要“告诉” input 一些事情的- 一些不能从它的props得到的东西。在这种情形下,我们想要“告诉”它,它现在也要改获取焦点了。然而,这里有些挑战。从`render()` 中返回的不是你实际组件的“孩子”组件,相反他是这些孩子在特定的时刻的一个*描述* - 一个快照。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>记着,从`render()` 中返回的不是你的*实际*渲染地孩子实例。从`render()` 中返回的仅仅是在你的组件的子层次结构中的这些孩子实例一个特定时刻的*描述*。
|
||||
|
||||
|
||||
这意味着你绝不该“拿”从`render()` 中返回的东西去做什么事情并期望有什么意义。
|
||||
|
||||
```javascript
|
||||
// 反模式:不能工作.
|
||||
render: function() {
|
||||
var myInput = <input />; // 我打算在这个上调用这个方法
|
||||
this.rememberThisInput = myInput; // input在未来的某个时间点上!YAY!
|
||||
return (
|
||||
<div>
|
||||
<div>...</div>
|
||||
{myInput}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
在这个例子中,`<input />` 仅仅是 `<input />` 的一个*描述*。这个描述不能用来为`<input />`创建一个*真实的* **背后的实例**。
|
||||
|
||||
那么对 input 的*真实的* 背后的实例,该怎么说呢?
|
||||
|
||||
## ref 字符串属性
|
||||
|
||||
React 假设你可以向任何的从`render()` 中返回的组件附加一个特别的属性。这个特殊的属性允许你引用任何的从`render()` 返回的东西对于有的**背后的实例**。而且保证在任何时间点都是合适的实例。
|
||||
|
||||
简单的说就是:
|
||||
|
||||
|
||||
1. 给任何从`render()` 中返回的东西赋一个`ref` 的属性,如下所示:
|
||||
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
|
||||
2. 在其他的代码中(通常是事件处理代码中),通过 `this.refs` 来访问 **背后的实例** 如下所示:
|
||||
|
||||
```javascript
|
||||
this.refs.myInput
|
||||
```
|
||||
|
||||
通过调用`this.refs.myInput` 你可以直接方法这个组建的DOM。
|
||||
|
||||
|
||||
## ref 回调属性
|
||||
|
||||
`ref` 属性可以用一个回调函数来替换一个名字。当这个组件装载好之后立即执行。被引用的组件被作为一个参数传入,这个回调函数可能立即使用这个组件,或保存这个引用,将来再用(或者两者都做)。
|
||||
|
||||
使用ES6的箭头函数,为从`render` 中返回的东西添加一个`ref` 属性非常简单:
|
||||
|
||||
```html
|
||||
render: function() {
|
||||
return <TextInput ref={(c) => this._input = c} />;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this._input.focus();
|
||||
},
|
||||
```
|
||||
|
||||
或
|
||||
|
||||
```html
|
||||
render: function() {
|
||||
return (
|
||||
<TextInput
|
||||
ref={function(input) {
|
||||
if (input != null) {
|
||||
input.focus();
|
||||
}
|
||||
}} />
|
||||
);
|
||||
},
|
||||
```
|
||||
|
||||
注意当引用的组件被卸载以及无论何时这个引用改变之后,旧的引用将会被用`null` 作为一个参数来调用。这避免了当实例被存储的情形下- 像第一个例子那样 - 引起的内存泄漏。注意像这个例子中这样,用inline 函数表达式写引用的时候,每次有更新的时候Reac看到的都是不同的函数对象,在引用被组件的实例调用之前,引用被用`null` 调用。
|
||||
|
||||
## 完整的例子
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
// 清空input
|
||||
this.setState({userInput: ''}, function() {
|
||||
// 当这个组件被再次渲染之后,这个代码执行
|
||||
this.refs.theInput.focus(); //获取焦点了!
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
Click to Focus and Reset
|
||||
</div>
|
||||
<input
|
||||
ref="theInput"
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
在这个例子中,我们的render函数返回了`<input />` 实例的一个描述。但是真的实例通过`this.refs.theInput` 访问。只要`ref="theInput"` 从`render` 中返回了, `this.refs.theInput` 就可以访问合适的实例。这个事件对于高级的(非DOM)的组件,例如`<Typeahead ref="myTypeahead" />` 也适用的。
|
||||
|
||||
|
||||
## 总结
|
||||
|
||||
在不方便通过Reactive的 `props` 和`state` 流的方式传递信息的时候,Refs是给一个特殊的子实例发送消息的重要的方法。然而,他们不应该成为你的应用程序的到哪里去的数据流的抽象。对于那些本质上来说非交互的情形来说,默认的,应该使用Reactive数据流而少用`ref` 。
|
||||
|
||||
### 优点:
|
||||
|
||||
- 在你的组件类中你可以定义任意的公开方法(例如在一个Typeahead定义一个reset方法),然后通过refs来调用这些方法(像这样`this.refs.myTypeahead.reset()`)。
|
||||
|
||||
- 执行 DOM操作,总是要求诸如`<input />` 这样的一个“原生”组件,并通过`this.refs.myInput` 来访问她的低层的MOD 节点。Refs是可以做成这个事的唯一的实践可行的方法。
|
||||
|
||||
- Refs自动管理!如果孩子被销毁了,它的ref也被销毁。在这里不用担心内存(除非你做了一些疯狂的事情来自己保持一个引用)。
|
||||
|
||||
### 小心:
|
||||
|
||||
- *绝对不要* 在组件的render方法内部- 获 当任何组件的render方法还在调用栈中执行的时候,访问refs 。
|
||||
- 如果你想要保护Google 闭包编译器崩溃的内力,确保绝不作为访问一个被特别的设置为一个字符串的属性。这就意味着,如果你用`ref="myRefString"` 来定义你的ref的话,你必须使用`this.refs['myRefsString']` 来访问。
|
||||
- 如果你不是用React做服务器编程的,在你的程序中,你首先的倾向是用refs来“让事情发生“。如果这是正是你的情况的话,花点时间,仔细的想想`state` 在这个组件的结构层次中应在在哪里使用。通常,正确的"拥有" 状态的地方是结构层次的高层。把状态放在那些地方通常可以消除使用`ref` 来”让事情发生” 的渴望 - 相反的,数据流通常能完成你的目标。
|
||||
@@ -5,7 +5,7 @@ permalink: more-about-refs.html
|
||||
prev: working-with-the-browser.html
|
||||
next: tooling-integration.html
|
||||
---
|
||||
After building your component, you may find yourself wanting to "reach out" and invoke methods on component instances returned from `render()`. In most cases, this should be unnecessary because the reactive data flow always ensures that the most recent props are sent to each child that is output from render(). However, there are a few cases where it still might be necessary or beneficial, so React provides an escape hatch known as `refs`. These `refs` (references) are especially useful when you need to: find the DOM markup rendered by a component (for instance, to position it absolutely), use React components in a larger non-React application, or transition your existing codebase to React.
|
||||
After building your component, you may find yourself wanting to "reach out" and invoke methods on component instances returned from `render()`. In most cases, this should be unnecessary because the reactive data flow always ensures that the most recent props are sent to each child that is output from `render()`. However, there are a few cases where it still might be necessary or beneficial, so React provides an escape hatch known as `refs`. These `refs` (references) are especially useful when you need to: find the DOM markup rendered by a component (for instance, to position it absolutely), use React components in a larger non-React application, or transition your existing codebase to React.
|
||||
|
||||
Let's look at how to get a ref, and then dive into a complete example.
|
||||
|
||||
@@ -91,11 +91,13 @@ In order to get a reference to a React component, you can either use `this` to g
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// Explicitly focus the text input using the raw DOM API.
|
||||
this.myTextInput.focus();
|
||||
if (this.myTextInput !== null) {
|
||||
this.myTextInput.focus();
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
// The ref attribute adds a reference to the component to
|
||||
// this.refs when the component is mounted.
|
||||
// The ref attribute is a callback that saves a reference to the
|
||||
// component to this.myTextInput when the component is mounted.
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref={(ref) => this.myTextInput = ref} />
|
||||
@@ -131,7 +133,7 @@ Refs are a great way to send a message to a particular child instance in a way t
|
||||
|
||||
### Cautions:
|
||||
|
||||
- *Never* access refs inside of any component's render method - or while any component's render method is even running anywhere in the call stack.
|
||||
- *Never* access refs inside of any component's render method – or while any component's render method is even running anywhere in the call stack.
|
||||
- If you want to preserve Google Closure Compiler advanced-mode crushing resilience, make sure to never access as a property what was specified as a string. This means you must access using `this.refs['myRefString']` if your ref was defined as `ref="myRefString"`.
|
||||
- If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where `state` should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use `ref`s to "make things happen" – instead, the data flow will usually accomplish your goal.
|
||||
- If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use `ref`s to "make things happen" – instead, the data flow will usually accomplish your goal.
|
||||
- Refs may not be attached to a [stateless function](/react/docs/reusable-components.html#stateless-functions), because the component does not have a backing instance. You can always wrap a stateless component in a standard composite component and attach a ref to the composite component.
|
||||
|
||||
@@ -1,109 +1,45 @@
|
||||
---
|
||||
id: more-about-refs-zh-CN
|
||||
title: 关于Refs的更多内容
|
||||
title: 对组件的refs
|
||||
permalink: more-about-refs-zh-CN.html
|
||||
prev: working-with-the-browser-zh-CN.html
|
||||
next: tooling-integration-zh-CN.html
|
||||
---
|
||||
从render方法返回你的UI结构以后,你也许发现自己想“接触”并且调用从 `render()`返回的组件实例上的方法。通常,这样做对于让数据流过你的应用并不是必须的,因为Reactive的数据流总是确保最新的`props` 被发送到 `render()`输出的每个子级。然而,有一些情况下它仍旧是必要或者有益的。
|
||||
在建立你的组件以后,你也许发现你想“接触”并且调用从 `render()`返回的组件实例上的方法。大部分情况下,这是不必要的因为响应式的数据流总是确保最近的 props 被送到每一个从 `render()` 输出的子级。然而,有一些情况下它仍旧是必要或者有益的,所以 React 提供了一个被称为 `refs` 的安全舱口。这些 `refs` (引用) 在你需要时特别有用 如:查找被组件绘制的 DOM 标记(例如,绝对定位它),使用 React 组件在一个大的非React组件里,或者转换你已有的代码库到React。
|
||||
|
||||
考虑这样一种场景,当你想要告诉一个`<input />` 元素(存在于你的实例的子层级)在你更新他的值为空字符串后获得焦点。
|
||||
让我们来看看怎样取得一个ref,然后深入完整的例子。
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
this.setState({userInput: ''}); // Clear the input
|
||||
// We wish to focus the <input /> now!
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
Click to Focus and Reset
|
||||
</div>
|
||||
<input
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
## 从 ReactDOM.render 返回的 ref
|
||||
|
||||
不要被 你在你的组件(它返回一个虚拟的DOM元素)里定义的 `render()` 迷惑了, [ReactDOM.render()](/react/docs/top-level-api.html#reactdom.render) 会返回一个对你的组件的 **backing instance** 的引用(或者 `null` for [stateless components](/react/docs/reusable-components.html#stateless-functions)).
|
||||
|
||||
|
||||
```js
|
||||
var myComponent = ReactDOM.render(<MyComponent />, myContainer);
|
||||
```
|
||||
|
||||
记住,不管怎样,JSX不会返回一个组件的实例!它只是一个 **ReactElement**: 一个轻量级的表达,告诉React被挂载的组件应该长什么样。
|
||||
|
||||
注意,在这个例子中,我们想 "告诉" input 一些东西 - 那些最后它不能从他的props推断出来的东西。在这个场景中我们想 "告诉" 它,它应该转为获得焦点。然而,有一些挑战。从`render()` 返回的东西不是你实际的 "子" 组件的组合,而是一个在某刻特定实例的子组件的 *描述* - 一个快照。
|
||||
```js
|
||||
var myComponentElement = <MyComponent />; // 这只是一个 ReactElement.
|
||||
|
||||
// 省略一些代码 ...
|
||||
|
||||
var myComponentInstance = ReactDOM.render(myComponentElement, myContainer);
|
||||
myComponentInstance.doSomething();
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 记住,从 `render()`返回的东西不是你的 *实际的* 被渲染出的子组件实例。从 `render()` 返回的东西仅仅是一个在特定时间你的组件的子层级中的子实例的 *描述*。
|
||||
> 这只应该用在顶层上。在组件内部,让你的 `props` 和 `state` 来处理和子组件的通信,或者使用其他获取ref的方法(string attribute or callbacks)。
|
||||
|
||||
## ref Callback 属性
|
||||
|
||||
这意味着你万万不要把你从`render()`返回的东西 "抓住不放" 然后期望它变成任何有意义的东西。
|
||||
React支持一种非常特殊的属性,你可以附加到任何的组件上。 `ref` 属性可以是一个回调函数,这个回调函数会在组件被挂载后立即执行。被引用的组件会被作为参数传递,回调函数可以用立即使用这个组件,或者保存引用以后使用(或者二者皆是)。
|
||||
|
||||
```javascript
|
||||
// 反面模式: 这行不通.
|
||||
render: function() {
|
||||
var myInput = <input />; // I'm going to try to call methods on this
|
||||
this.rememberThisInput = myInput; // input at some point in the future! YAY!
|
||||
return (
|
||||
<div>
|
||||
<div>...</div>
|
||||
{myInput}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
简单的说就是添加一个 `ref` 属性到任何从 `render` 返回的东西上:
|
||||
|
||||
在这个例子中,`<input />` 仅仅是一个`<input />` 的 *描述*。 这个描述被用于为`<input />`创建一个 *真实的* **支持实例(backing instance)**
|
||||
|
||||
所以我们如何与input的 *真实的*支持实例对话?
|
||||
|
||||
## ref String 属性
|
||||
|
||||
React支持一种非常特殊的属性,你可以附加到任何从`render()`输出的组件上。这个特殊的属性允许你引用任何从`render()`返回的东西的对应 **支持实例(backing instance)** 。它总是保证是适当的实例,在任何时点上。
|
||||
|
||||
就是这么简单:
|
||||
|
||||
1. 赋值`ref`属性为任何从`render` 返回的东西,比如:
|
||||
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
|
||||
2. 在其他一些代码中(典型的事件处理代码),通过`this.refs`访问 **支持实例(backing instance)**,如:
|
||||
|
||||
```javascript
|
||||
this.refs.myInput
|
||||
```
|
||||
|
||||
你可以直接通过调用`ReactDOM.findDOMNode(this.refs.myInput)` 访问组件的DOM node。
|
||||
|
||||
|
||||
## ref 回调属性
|
||||
|
||||
`ref` 属性可以是一个回调函数而不是名字。这个回调函数将会在组件挂载以后立即执行。被引用的组件将被作为参数传递,并且回调函数可以立即使用组件,或者保存引用将来使用(或两者都是)。
|
||||
|
||||
通过使用ES6的箭头函数,它像添加一个`ref`属性到任何从`render`返回的东西一样简单。
|
||||
|
||||
```html
|
||||
render: function() {
|
||||
return <TextInput ref={(c) => this._input = c} />;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this._input.focus();
|
||||
},
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```html
|
||||
```js
|
||||
render: function() {
|
||||
return (
|
||||
<TextInput
|
||||
@@ -115,60 +51,87 @@ React支持一种非常特殊的属性,你可以附加到任何从`render()`
|
||||
);
|
||||
},
|
||||
```
|
||||
或者使用ES6的箭头函数:
|
||||
|
||||
```js
|
||||
render: function() {
|
||||
return <TextInput ref={(c) => this._input = c} />;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this._input.focus();
|
||||
},
|
||||
```
|
||||
|
||||
当连接一个ref到一个DOM组件如 `<div />`,你取回DOM节点;当连接一个ref到一个复合组件如 `<TextInput />`,你会得到React类的实例。在后一种情况下,你可以调用任何那个组件的类暴露的方法。
|
||||
|
||||
注意当被引用的组件卸载和每当ref变动,旧的ref将会被以`null`做参数调用。这阻止了在实例被保存的情况下的内存泄露,如第一个例子。注意当像在这里的例子,使用内联函数表达式写refs,React在每次更新都看到不同的函数对象,ref将会被以`null` 立即调用在它被以组件实例调用前。
|
||||
|
||||
## ref String 属性
|
||||
|
||||
## 完成的示例
|
||||
React同样支持使用一个字符串(代替回调函数)在任意组件上作为一个 ref prop,尽管这个方法在这点上主要是遗留物。
|
||||
|
||||
1. 赋值`ref`属性为任何从`render` 返回的东西,比如:
|
||||
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
|
||||
2. 在其他一些代码中(典型的事件处理代码),通过`this.refs`访问 **支持实例(backing instance)**,如:
|
||||
|
||||
```javascript
|
||||
var input = this.refs.myInput;
|
||||
var inputValue = input.value;
|
||||
var inputRect = input.getBoundingClientRect();
|
||||
```
|
||||
|
||||
## 完整的示例
|
||||
为了获取一个React组件的引用,你既可以使用 `this` 来获取当前的React组件,也可以使用一个 ref 来获取一个你拥有的组件的引用。他们像这样工作:
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
// Clear the input
|
||||
this.setState({userInput: ''}, function() {
|
||||
// This code executes after the component is re-rendered
|
||||
ReactDOM.findDOMNode(this.refs.theInput).focus(); // Boom! Focused!
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
Click to Focus and Reset
|
||||
</div>
|
||||
<input
|
||||
ref="theInput"
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// Explicitly focus the text input using the raw DOM API.
|
||||
this.myTextInput.focus();
|
||||
},
|
||||
render: function() {
|
||||
// The ref attribute adds a reference to the component to
|
||||
// this.refs when the component is mounted.
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref={(ref) => this.myTextInput = ref} />
|
||||
<input
|
||||
type="button"
|
||||
value="Focus the text input"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<MyComponent />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
在这个例子中, 我们的render函数返回一个 `<input />` 实例的描述。但是真正的实例通过 `this.refs.theInput` 访问。只要带有`ref="theInput"`的子组件从 `render`被返回,`this.refs.theInput` 就可以访问正确的实例。这甚至在更高层(non-DOM)的组件上生效,比如`<Typeahead ref="myTypeahead" />`。
|
||||
在这个例子中,我们获得一个对 text input **backing instance** 的引用 并且当按钮被点击时我们调用 `focus()`。
|
||||
|
||||
对于复合组件,引用会指向一个组件类的实例所以你可以调用那个类定义的任何方法。如果你需要访问那个组件的底层的DOM节点,你可以使用 [ReactDOM.findDOMNode](/react/docs/top-level-api.html#reactdom.finddomnode) 作为一个 `安全舱口` 但是我们不推荐这样,因为它打破了封装,在大多数情况下都有一个清晰的方法来以React模式构建你的代码.
|
||||
|
||||
## 总结
|
||||
|
||||
Refs是一种很好的发送消息给特定子实例(通过流式的Reactive `props` 和 `state`来做会不方便)的方式。它们应该,不论怎样,不是你数据流通你的应用的首选。默认方式,使用Reactive数据流并为本身不是reactive的用例保存`ref`。
|
||||
Refs是一种很好的发送消息给特定子实例(通过流式的Reactive `props` 和 `state`来做会不方便)的方式。它们应该,不论怎样,不是你数据流通你的应用的首选。默认情况下,使用响应式数据流,并为本身不是reactive的用例保存`ref`s。
|
||||
|
||||
### 优点:
|
||||
|
||||
- 你可以在你的组件类里定义任何的公开方法(比如在一个Typeahead的重置方法)然后通过refs调用那些公开方法(比如`this.refs.myTypeahead.reset()`)。
|
||||
- 实行DOM测量几乎总是需要接触到"原生" 组件比如 `<input />` 并且`ReactDOM.findDOMNode(this.refs.myInput)`通过访问它的底层DOM 节点。 Refs 是唯一一个可靠的完成这件事的实际方式。
|
||||
- 你可以在你的组件类里定义任何的公开方法(比如在一个Typeahead的重置方法)然后通过refs调用那些公开方法(比如`this.refs.myTypeahead.reset()`)。在大多数情况下,使用内建的React数据流更清晰,而不是使用强制的ref。
|
||||
- 实行DOM测量几乎总是需要接触到 "原生" 组件比如 `<input />` 并且通过 ref 访问它的底层DOM节点。 Refs 是唯一一个可靠的完成这件事的实际方式。
|
||||
- Refs 是为你自动管理的!如果子级被销毁了,它的ref也同样为你销毁了。这里不用担心内存(除非你做了一些疯狂的事情来自己保持一份引用)。
|
||||
|
||||
### 注意事项:
|
||||
|
||||
- *绝不* 在任何组件的 render 方法中访问 refs - 或者当任何组件的render方法还在调用栈上的任何地方运行时。
|
||||
- 如果你想要保留Google Closure Compiler Crushing resilience,务必不要把指明为字符串的以属性来访问。这意味这你必须用`this.refs['myRefString']`访问,如果你的ref被定义为`ref="myRefString"`。
|
||||
- 如果你没有用React写过数个程序,你的第一反应通常是打算试着用refs来在你的应用里"让事情发生"。如果是这样,花一些时间并且更精密的思考`state`应该属于组件层级的哪个位置。常常,这会变得清晰:正确的"拥有"那个属性的地方应该在层级的更高层上。把state放在那里往往消除了任何使用`ref`来 "让事情发生"的渴望 - 作为替代,数据流通常将完成你的目标。
|
||||
|
||||
- 如果你想要保留Google Closure Compiler advanced-mode crushing resilience,务必不要以属性的方式访问指明为字符串的属性。这意味这你必须用`this.refs['myRefString']`访问,如果你的ref被定义为`ref="myRefString"`。
|
||||
- 如果你没有用React写过数个程序,你的第一反应通常是打算试着用refs来在你的应用里"让事情发生"。如果是这样,花一些时间并且更精密的思考`state`应该属于组件层级的哪个位置。常常,这会变得清晰:正确的"拥有"那个属性的地方应该在层级的更高层上。把state放在那里 往往消除了任何使用`ref`s 来 "让事情发生"的渴望 - 作为替代,数据流通常将完成你的目标。
|
||||
- Refs 不能连接到一个 [stateless function(无状态函数)](/react/docs/reusable-components.html#stateless-functions),因为这些组件没有支持实例。你总是可以包装一个无状态组件在一个标准复合组件里并且连接一个ref到这个复合组件。
|
||||
|
||||
@@ -22,7 +22,7 @@ We have instructions for building from `master` [in our GitHub repository](https
|
||||
|
||||
### In-browser JSX Transform
|
||||
|
||||
If you like using JSX, Babel provides an [in-browser ES6 and JSX transformer for development](http://babeljs.io/docs/usage/browser/) called browser.js that can be included from a `babel-core` npm release or from [CDNJS](http://cdnjs.com/libraries/babel-core). Include a `<script type="text/babel">` tag to engage the JSX transformer.
|
||||
If you like using JSX, Babel 5 provided an in-browser ES6 and JSX transformer for development called browser.js that can be included from [CDNJS](http://cdnjs.com/libraries/babel-core/5.8.34). Include a `<script type="text/babel">` tag to engage the JSX transformer.
|
||||
|
||||
> Note:
|
||||
>
|
||||
|
||||
@@ -14,7 +14,6 @@ next: addons-zh-CN.html
|
||||
|
||||
我们提供了CDN-hosted版本的React[在我们的下载页面](/react/downloads.html).这些预构建的文件使用UMD模块格式。将他们放进一个简单的`<script>` 标签将会注入一个`React` 全局变量到你的环境里。这也同样在CommonJS 和 AMD 环境里开箱即用。
|
||||
|
||||
|
||||
### 使用 master
|
||||
|
||||
我们[在我们的 GitHub repository](https://github.com/facebook/react)有从`master`构建的说明。我们在`build/modules` 下构建了一个CommonJS模块的树,你可以把它放到任何支持CommonJS的环境或者打包工具里。
|
||||
@@ -23,19 +22,27 @@ next: addons-zh-CN.html
|
||||
|
||||
### 浏览器中的JSX转化
|
||||
|
||||
如果你喜欢使用JSX,Babel提供了一个被称为browser.js的[开发用的浏览器中的 ES6 和 JSX 转换器](http://babeljs.io/docs/usage/browser/) ,它可以从`babel-core` npm release 或者[CDNJS](http://cdnjs.com/libraries/babel-core) 中 include。Include `<script type="text/babel">` 标记来使用 JSX 转换器.
|
||||
如果你喜欢使用JSX,Babel5 提供了被称为browser.js 用于开发的一个浏览器内的 ES6 和 JSX 转换器,它可以从 [CDNJS](http://cdnjs.com/libraries/babel-core/5.8.34) 引用。Include `<script type="text/babel">` 标记来使用 JSX 转换器.
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 浏览器中的JSX转换器相当大并且导致额外的本可避免的客户端计算。不要在生产环境中使用 - 见下一节。
|
||||
|
||||
|
||||
### 投入生产: 预编译 JSX
|
||||
|
||||
如果你有[npm](https://www.npmjs.com/),你可以运行 `npm install -g babel`. Babel 对React v0.12 和 v0.13 有内建的支持。 标签被自动转化为它们的等价物`React.createElement(...)`, `displayName` 被自动推断并添加到所有的React.createClass 调用。
|
||||
如果你有[npm](https://www.npmjs.com/),你可以运行 `npm install -g babel-cli`. Babel 对React v0.12+ 有内建支持。 标签被自动转化为它们的等价物`React.createElement(...)`, `displayName` 被自动推断并添加到所有的React.createClass 调用。
|
||||
|
||||
这个工具会把使用JSX语法的文件转化为简单的可直接在浏览器运行的JavaScript文件。它同样将为你监视目录并自动转化文件当他们变动时;例如:`babel --watch src/ --out-dir lib/`.
|
||||
|
||||
从 Babel 6 开始,默认不再包含转换。这意味这必须在运行 `babel` 命令时指定选项,或者 `.babelrc` 必须指定选项。附加的捆绑了一大批转化的包(presets)也同样需要被安装.协同React工作最常用的是 `es2015` 和 `react` presets.更多关于 Babel 变化的信息可以在 [Babel 6 博客发布的信息](http://babeljs.io/blog/2015/10/29/6.0.0/)上找到.
|
||||
|
||||
这里是一个要使用ES2015 语法和 React 你该怎样做的例子:
|
||||
|
||||
```
|
||||
npm install babel-preset-es2015 babel-preset-react
|
||||
babel --presets es2015,react --watch src/ --out-dir lib/
|
||||
```
|
||||
|
||||
默认模式下带有`.js`后缀的JSX文件被转化。运行 `babel --help` 获取更多关于如何使用 Babel 的信息。
|
||||
|
||||
输出的例子:
|
||||
@@ -68,7 +75,6 @@ var HelloMessage = React.createClass({
|
||||
ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
|
||||
```
|
||||
|
||||
|
||||
### 有帮助的开源项目
|
||||
|
||||
开源社区已经创建了一些集成JSX到数个编辑器和构建系统的工具。参见[JSX integrations](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations) 查看全部列表。
|
||||
开源社区已经创建了一些集成JSX到数个编辑器和构建系统的工具。全部列表请见[JSX integrations](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations) 。
|
||||
|
||||
@@ -14,10 +14,11 @@ The React add-ons are a collection of useful utility modules for building React
|
||||
- [`createFragment`](create-fragment.html), to create a set of externally-keyed children.
|
||||
- [`update`](update.html), a helper function that makes dealing with immutable data in JavaScript easier.
|
||||
- [`PureRenderMixin`](pure-render-mixin.html), a performance booster under certain situations.
|
||||
- [`shallowCompare`](shallow-compare.html), a helper function that performs a shallow comparison for props and state in a component to decide if a component should update.
|
||||
|
||||
The add-ons below are in the development (unminified) version of React only:
|
||||
|
||||
- [`TestUtils`](test-utils.html), simple helpers for writing test cases (unminified build only).
|
||||
- [`Perf`](perf.html), for measuring performance and giving you hint where to optimize.
|
||||
- [`TestUtils`](test-utils.html), simple helpers for writing test cases.
|
||||
- [`Perf`](perf.html), a performance profiling tool for finding optimization opportunities.
|
||||
|
||||
To get the add-ons, install them individually from npm (e.g., `npm install react-addons-pure-render-mixin`). We don't support using the addons if you're not using npm.
|
||||
|
||||
@@ -6,7 +6,7 @@ prev: tooling-integration-zh-CN.html
|
||||
next: animation-zh-CN.html
|
||||
---
|
||||
|
||||
`React.addons` 是我们放置一些用来构建React apps的有用的工具的地方。 **这些应该被认为是实验性的** 但是最终批量进入核心代码或者一个有用的工具库中:
|
||||
React插件是一系列的用来构建 React app的有用模块。 **这些应该被认为是实验性的** 并趋向于比core变动更频繁。
|
||||
|
||||
- [`TransitionGroup` 和 `CSSTransitionGroup`](animation.html), 用来处理通常不能简单实现的动画和转换,比如在组件移除之前。
|
||||
- [`LinkedStateMixin`](two-way-binding-helpers.html), 简化用户的表单输入数据与组件状态的协调。
|
||||
@@ -14,12 +14,11 @@ next: animation-zh-CN.html
|
||||
- [`createFragment`](create-fragment.html), 创建一组外键的子级。
|
||||
- [`update`](update.html), 一个使不可变数据在JavaScript里更易处理的辅助函数。
|
||||
- [`PureRenderMixin`](pure-render-mixin.html), 一个特定情况下的性能优化器。
|
||||
- [`shallowCompare`](shallow-compare.html), 一个辅助函数,用来对 props 和 state在组件里 执行浅比较 以决定一个组件是否应该更新。
|
||||
|
||||
下面的插件只存在开发版(未压缩)React中:
|
||||
|
||||
- [`TestUtils`](test-utils.html), 用于写测试用例的简单的辅助工具(仅存在于未压缩版本)。
|
||||
- [`Perf`](perf.html), 用于测量性能并给你提示哪里可以优化。
|
||||
- [`TestUtils`](test-utils.html), 用于写测试用例的简单的辅助工具。
|
||||
- [`Perf`](perf.html), 一个用于查找优化机会的性能分析工具。
|
||||
|
||||
要获取插件,使用 `react-with-addons.js` (和它的压缩副本)而不是通常的 `react.js`。
|
||||
|
||||
当从npm使用react包时,简单的用`require('react/addons')` 代替 `require('react')` 来获取带有所有插件的React。
|
||||
要获取插件,单独从npm安装他们(例如 `npm install react-addons-pure-render-mixin`).我们不支持使用插件如果你没有用npm.
|
||||
|
||||
@@ -29,7 +29,7 @@ var TodoList = React.createClass({
|
||||
this.setState({items: newItems});
|
||||
},
|
||||
handleRemove: function(i) {
|
||||
var newItems = this.state.items;
|
||||
var newItems = this.state.items.slice();
|
||||
newItems.splice(i, 1);
|
||||
this.setState({items: newItems});
|
||||
},
|
||||
|
||||
@@ -17,7 +17,7 @@ React 提供了一个 `ReactTransitionGroup` 插件作为动画的底层API,和
|
||||
`ReactCSSTransitionGroup` 是 `ReactTransitions` 的接口。这是一个简单的元素,包裹了所有你感兴趣的动画组件。这里是一个淡入和淡出列表项目的例子。
|
||||
|
||||
```javascript{28-30}
|
||||
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
|
||||
|
||||
var TodoList = React.createClass({
|
||||
getInitialState: function() {
|
||||
@@ -29,7 +29,7 @@ var TodoList = React.createClass({
|
||||
this.setState({items: newItems});
|
||||
},
|
||||
handleRemove: function(i) {
|
||||
var newItems = this.state.items;
|
||||
var newItems = this.state.items.slice();
|
||||
newItems.splice(i, 1);
|
||||
this.setState({items: newItems});
|
||||
},
|
||||
@@ -101,11 +101,11 @@ var TodoList = React.createClass({
|
||||
```css
|
||||
.example-appear {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
}
|
||||
|
||||
.example-appear.example-appear-active {
|
||||
opacity: 1;
|
||||
transition: opacity .5s ease-in;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -173,7 +173,7 @@ var TodoList = React.createClass({
|
||||
在上面的例子中,我们渲染了一系列的项目到`ReactCSSTransitionGroup`里。然而 `ReactCSSTransitionGroup` 的子级同样可以是一个或零个项目。这使它能够动画化单个元素的进入和离开。同样,你可以动画化一个新的元素替换当前元素。例如,我们可以像这样实现一个简单的图片轮播器:
|
||||
|
||||
```javascript{10-12}
|
||||
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
|
||||
|
||||
var ImageCarousel = React.createClass({
|
||||
propTypes: {
|
||||
@@ -201,7 +201,7 @@ var ImageCarousel = React.createClass({
|
||||
|
||||
## 底层 API: `ReactTransitionGroup`
|
||||
|
||||
`ReactTransitionGroup`是动画的基础。它通过 `React.addons.TransitionGroup` 访问。当子级被声明式的从其中添加或移除(就像上面的例子)时,特殊的生命周期挂钩会在它们上面被调用。
|
||||
`ReactTransitionGroup`是动画的基础。它通过 `require('react-addons-transition-group')` 访问。当子级被声明式的从其中添加或移除(就像上面的例子)时,特殊的生命周期挂钩会在它们上面被调用。
|
||||
|
||||
### `componentWillAppear(callback)`
|
||||
|
||||
@@ -237,11 +237,8 @@ var ImageCarousel = React.createClass({
|
||||
</ReactTransitionGroup>
|
||||
```
|
||||
|
||||
每一个React能渲染的DOM组件都是可用的。然而,`组件`不需要是一个DOM组件。它可以是任何你想要的React组件;甚至是你自己已经写好的!
|
||||
每一个React能渲染的DOM组件都是可用的。然而,`组件`不需要是一个DOM组件。它可以是任何你想要的React组件;甚至是你自己已经写好的!只要写 `component={List}` 你的组件会收到 `this.props.children`
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> v0.12之前,当使用DOM组件时,`组件` prop 需要是一个对`React.DOM.*`的引用。既然组件简单的被传递到 `React.createElement`,它现在必然是一个字符串。复合组件必须传递工厂函数(factory)。
|
||||
|
||||
任何额外的、用户定义的属性将会成为已渲染的组件的属性。例如,以下是你将如何渲染一个带有css类的 `<ul>`:
|
||||
|
||||
|
||||
32
docs/docs/10.10-shallow-compare.md
Normal file
32
docs/docs/10.10-shallow-compare.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
id: shallow-compare
|
||||
title: Shallow Compare
|
||||
permalink: shallow-compare.html
|
||||
prev: perf.html
|
||||
next: advanced-performance.html
|
||||
---
|
||||
|
||||
`shallowCompare` is a helper function to achieve the same functionality as `PureRenderMixin` while using ES6 classes with React.
|
||||
|
||||
If your React component's render function is "pure" (in other words, it renders the same result given the same props and state), you can use this helper function for a performance boost in some cases.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
var shallowCompare = require('react-addons-shallow-compare');
|
||||
export class SampleComponent extends React.Component {
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return shallowCompare(this, nextProps, nextState);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className={this.props.className}>foo</div>;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`shallowCompare` performs a shallow equality check on the current `props` and `nextProps` objects as well as the current `state` and `nextState` objects.
|
||||
It does this by iterating on the keys of the objects being compared and returning false when the value of a key in each object are not strictly equal.
|
||||
|
||||
`shallowCompare` returns `true` if the shallow comparison for props or state fails and therefore the component should update.
|
||||
`shallowCompare` returns `false` if the shallow comparison for props and state both pass and therefore the component does not need to update.
|
||||
32
docs/docs/10.10-shallow-compare.zh-CN.md
Normal file
32
docs/docs/10.10-shallow-compare.zh-CN.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
id: shallow-compare-zh-CN
|
||||
title: 浅比较
|
||||
permalink: shallow-compare-zh-CN.html
|
||||
prev: perf-zh-CN.html
|
||||
next: advanced-performance-zh-CN.html
|
||||
---
|
||||
|
||||
`shallowCompare` 是一个辅助函数 在以ES6类使用React时,完成和 `PureRenderMixin` 相同的功能。
|
||||
|
||||
如果你的React组件的绘制函数是 “干净的” (换句话说,它在给定的 props 和 state 下绘制相同的结果),你可以使用这个辅助函数以在某些情况下提升性能。
|
||||
|
||||
例如:
|
||||
|
||||
```js
|
||||
var shallowCompare = require('react-addons-shallow-compare');
|
||||
export class SampleComponent extends React.Component {
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return shallowCompare(this, nextProps, nextState);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className={this.props.className}>foo</div>;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`shallowCompare` 对当前的 `props` 和 `nextProps`对象 执行一个浅的相等检查,同样对于 `state` 和 `nextState`对象。
|
||||
它 通过迭代比较对象的keys 并在 对象的key值不严格相等时返回false 实现此功能.
|
||||
|
||||
`shallowCompare` 返回 `true` 如果对 props 或 state的浅比较失败,因此组件应该更新。
|
||||
`shallowCompare` 返回 `false` 如果对 props 或 state的浅比较都通过了,因此组件不应该更新。
|
||||
117
docs/docs/10.2-form-input-binding-sugar.zh-CN.md
Normal file
117
docs/docs/10.2-form-input-binding-sugar.zh-CN.md
Normal file
@@ -0,0 +1,117 @@
|
||||
---
|
||||
id: two-way-binding-helpers-zh-CN
|
||||
title: 双向绑定辅助
|
||||
permalink: two-way-binding-helpers-zh-CN.html
|
||||
prev: animation-zh-CN.html
|
||||
next: test-utils-zh-CN.html
|
||||
---
|
||||
|
||||
`ReactLink` 是一个用React表达双向绑定的简单方法。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 在 React v15 中 ReactLink 被弃用了。推荐明确的设置值和变动的处理,而不是使用 ReactLink。
|
||||
|
||||
在React里,数据单向流动: 从拥有者到子级。这是因为数据只单向流动[the Von Neumann model of computing](https://en.wikipedia.org/wiki/Von_Neumann_architecture)。你可以把它想象为 “单向数据绑定”。
|
||||
|
||||
然而,有很多应用需要你去读某些数据并回流他们到你的程序。例如,当开发forms,你会常常想更新一些React `state` 当你收到用户输入的时候。或者也许你想在JavaScript完成布局并相应一些DOM元素大小的变化。
|
||||
|
||||
在React里,你可以用监听 "change" 事件来实现它,从你的数据源(通常是DOM)读取并在你的某个组件调用 `setState()` 。明确的"Closing the data flow loop" 致使了更容易理解和维护的程序。更多信息见[our forms documentation](/react/docs/forms.html).
|
||||
|
||||
双向绑定 -- 隐含的强迫DOM里的某些值总是和某些React `state` 同步 -- 简洁并支持大量多样的应用。 我们提供了 `ReactLink`:设置如上描述的通用数据回流模式的语法糖,或者 "linking" 某些数据结构到 React `state`.
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> `ReactLink` 只是一层对 `onChange`/`setState()` 模式的薄包装。它没有根本性的改变你的React应用里数据如何流动。
|
||||
|
||||
## ReactLink: 之前和之后
|
||||
|
||||
这里有一个简单的 不用 `ReactLink` 的 form 例子:
|
||||
|
||||
```javascript
|
||||
var NoLink = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {message: 'Hello!'};
|
||||
},
|
||||
handleChange: function(event) {
|
||||
this.setState({message: event.target.value});
|
||||
},
|
||||
render: function() {
|
||||
var message = this.state.message;
|
||||
return <input type="text" value={message} onChange={this.handleChange} />;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
这个工作的很好并且数据如何流动很清晰,然而,当有大量的 form fields时,可能会有些冗长。让我们使用 `ReactLink` 来节省我们的输入:
|
||||
|
||||
```javascript{4,9}
|
||||
var LinkedStateMixin = require('react-addons-linked-state-mixin');
|
||||
|
||||
var WithLink = React.createClass({
|
||||
mixins: [LinkedStateMixin],
|
||||
getInitialState: function() {
|
||||
return {message: 'Hello!'};
|
||||
},
|
||||
render: function() {
|
||||
return <input type="text" valueLink={this.linkState('message')} />;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
`LinkedStateMixin` 添加了一个 `linkState()` 方法到你的React组件。`linkState()` 返回一个 `ReactLink` 包含当前React state值的对象和一个改变它的回调函数。
|
||||
|
||||
`ReactLink` 对象可以作为props在树中上下传递,所以很容易(显示的)在深层次的组件和高层次的state之间 设置双向绑定。
|
||||
|
||||
注意 checkboxes 有一个关于他们 `value` 属性的特殊行为,这个行为是 如果checkbox被选中 值会在表单提交时被发送。 `value` 不会 checkbox 选中或是不选中时更新。对于checkboxes,你应该用`checkedLink` 代替 `valueLink`:
|
||||
```
|
||||
<input type="checkbox" checkedLink={this.linkState('booleanValue')} />
|
||||
```
|
||||
|
||||
## 引擎盖下
|
||||
|
||||
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.
|
||||
|
||||
### ReactLink Without LinkedStateMixin
|
||||
|
||||
```javascript{5-7,9-12}
|
||||
var WithoutMixin = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {message: 'Hello!'};
|
||||
},
|
||||
handleChange: function(newValue) {
|
||||
this.setState({message: newValue});
|
||||
},
|
||||
render: function() {
|
||||
var valueLink = {
|
||||
value: this.state.message,
|
||||
requestChange: this.handleChange
|
||||
};
|
||||
return <input type="text" valueLink={valueLink} />;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
As you can see, `ReactLink` objects are very simple objects that just have a `value` and `requestChange` prop. And `LinkedStateMixin` is similarly simple: it just populates those fields with a value from `this.state` and a callback that calls `this.setState()`.
|
||||
|
||||
### ReactLink Without valueLink
|
||||
|
||||
```javascript
|
||||
var LinkedStateMixin = require('react-addons-linked-state-mixin');
|
||||
|
||||
var WithoutLink = React.createClass({
|
||||
mixins: [LinkedStateMixin],
|
||||
getInitialState: function() {
|
||||
return {message: 'Hello!'};
|
||||
},
|
||||
render: function() {
|
||||
var valueLink = this.linkState('message');
|
||||
var handleChange = function(e) {
|
||||
valueLink.requestChange(e.target.value);
|
||||
};
|
||||
return <input type="text" value={valueLink.value} onChange={handleChange} />;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
The `valueLink` prop is also quite simple. It simply handles the `onChange` event and calls `this.props.valueLink.requestChange()` and also uses `this.props.valueLink.value` instead of `this.props.value`. That's it!
|
||||
11
docs/docs/10.3-class-name-manipulation.zh-CN.md
Normal file
11
docs/docs/10.3-class-name-manipulation.zh-CN.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
id: class-name-manipulation-zh-CN
|
||||
title: 类名操纵
|
||||
permalink: class-name-manipulation-zh-CN.html
|
||||
prev: two-way-binding-helpers-zh-CN.html
|
||||
next: test-utils-zh-CN.html
|
||||
---
|
||||
|
||||
> NOTE:
|
||||
>
|
||||
> 此模块已被弃用; 用 [JedWatson/classnames](https://github.com/JedWatson/classnames) 替代.
|
||||
@@ -30,7 +30,7 @@ React.addons.TestUtils.Simulate.click(node);
|
||||
|
||||
```javascript
|
||||
var node = ReactDOM.findDOMNode(this.refs.input);
|
||||
node.value = 'giraffe'
|
||||
node.value = 'giraffe';
|
||||
React.addons.TestUtils.Simulate.change(node);
|
||||
React.addons.TestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
|
||||
```
|
||||
|
||||
@@ -36,7 +36,7 @@ ReactTestUtils.Simulate.click(node);
|
||||
```javascript
|
||||
// <input ref="input" />
|
||||
var node = this.refs.input;
|
||||
node.value = 'giraffe'
|
||||
node.value = 'giraffe';
|
||||
ReactTestUtils.Simulate.change(node);
|
||||
ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
|
||||
```
|
||||
|
||||
@@ -36,14 +36,14 @@ ReactTestUtils.Simulate.click(node);
|
||||
```javascript
|
||||
// <input ref="input" />
|
||||
var node = this.refs.input;
|
||||
node.value = 'giraffe'
|
||||
node.value = 'giraffe';
|
||||
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.*
|
||||
|
||||
`Simulate` has a method for every event that React understands.
|
||||
`Simulate` has a method for [every event that React understands](/react/docs/events.html#supported-events).
|
||||
|
||||
### renderIntoDocument
|
||||
|
||||
@@ -232,6 +232,7 @@ After `render` has been called, returns shallowly rendered output. You can then
|
||||
Then you can assert:
|
||||
|
||||
```javascript
|
||||
var renderer = ReactTestUtils.createRenderer();
|
||||
result = renderer.getRenderOutput();
|
||||
expect(result.type).toBe('div');
|
||||
expect(result.props.children).toEqual([
|
||||
|
||||
244
docs/docs/10.4-test-utils.zh-CN.md
Normal file
244
docs/docs/10.4-test-utils.zh-CN.md
Normal file
@@ -0,0 +1,244 @@
|
||||
---
|
||||
id: test-utils-zh-CN
|
||||
title: 测试工具
|
||||
permalink: test-utils-zh-CN.html
|
||||
prev: two-way-binding-helpers-zh-CN.html
|
||||
next: clone-with-props-zh-CN.html
|
||||
---
|
||||
|
||||
`ReactTestUtils` 使你在你选择的测试框架中 (我们使用 [Jest](https://facebook.github.io/jest/)) 测试 React 组件变得容易。
|
||||
|
||||
```
|
||||
var ReactTestUtils = require('react-addons-test-utils');
|
||||
```
|
||||
|
||||
### Simulate
|
||||
|
||||
```javascript
|
||||
Simulate.{eventName}(
|
||||
DOMElement element,
|
||||
[object eventData]
|
||||
)
|
||||
```
|
||||
|
||||
模拟一个在 DOM 节点上带有可选 `eventData` 事件数据的事件派遣(event dispatch)。**这可能是 `ReactTestUtils` 里单独最有用的工具。**
|
||||
|
||||
**点击一个元素**
|
||||
|
||||
```javascript
|
||||
// <button ref="button">...</button>
|
||||
var node = this.refs.button;
|
||||
ReactTestUtils.Simulate.click(node);
|
||||
```
|
||||
|
||||
**改变 input 域的值然后点击 回车。**
|
||||
|
||||
```javascript
|
||||
// <input ref="input" />
|
||||
var node = this.refs.input;
|
||||
node.value = 'giraffe';
|
||||
ReactTestUtils.Simulate.change(node);
|
||||
ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
|
||||
```
|
||||
|
||||
*注意你将必须提供任何你在你的组件里使用的事件属性(例如 keyCode, which, 等等)因为React没有为你创建任何这类东西。*
|
||||
|
||||
`Simulate` has a method for [every event that React understands](/react/docs/events.html#supported-events).
|
||||
|
||||
### renderIntoDocument
|
||||
|
||||
```javascript
|
||||
ReactComponent renderIntoDocument(
|
||||
ReactElement instance
|
||||
)
|
||||
```
|
||||
|
||||
渲染一个组件到 document 里的 detached DOM 节点。**这个函数需要一个 DOM。**
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 在你 import React **之前**,你需要让 `window`, `window.document` 和 `window.document.createElement` 全局可用。
|
||||
不然 React 会认为它不能访问 DOM 然后类似 `setState` 的方法会不工作。
|
||||
|
||||
### mockComponent
|
||||
|
||||
```javascript
|
||||
object mockComponent(
|
||||
function componentClass,
|
||||
[string mockTagName]
|
||||
)
|
||||
```
|
||||
|
||||
传入一个 mocked 组件模块到这个方法来给它增加有用的方法,使它可以被用作 dummy React 组件。代替像通常一样的渲染,组件会成为一个简单的包含了任意被提供的子级的 `<div>` (或者其他 tag 名,如果提供了 `mockTagName`)
|
||||
|
||||
### isElement
|
||||
|
||||
```javascript
|
||||
boolean isElement(
|
||||
ReactElement element
|
||||
)
|
||||
```
|
||||
|
||||
返回 `true` 如果 `element` 是任意的 ReactElement。
|
||||
|
||||
### isElementOfType
|
||||
|
||||
```javascript
|
||||
boolean isElementOfType(
|
||||
ReactElement element,
|
||||
function componentClass
|
||||
)
|
||||
```
|
||||
|
||||
返回 `true` 如果 `element` 是一个类型是 React `componentClass` 的 ReactElement。
|
||||
|
||||
### isDOMComponent
|
||||
|
||||
```javascript
|
||||
boolean isDOMComponent(
|
||||
ReactComponent instance
|
||||
)
|
||||
```
|
||||
|
||||
返回 `true` 如果 `instance` 是一个 DOM 组件 (比如一个 `<div>` 或者 `<span>`)。
|
||||
|
||||
### isCompositeComponent
|
||||
|
||||
```javascript
|
||||
boolean isCompositeComponent(
|
||||
ReactComponent instance
|
||||
)
|
||||
```
|
||||
|
||||
返回 `true` 如果 `instance` 是一个复合组件 (由 `React.createClass()` 创建)。
|
||||
|
||||
### isCompositeComponentWithType
|
||||
|
||||
```javascript
|
||||
boolean isCompositeComponentWithType(
|
||||
ReactComponent instance,
|
||||
function componentClass
|
||||
)
|
||||
```
|
||||
|
||||
返回 `true` 如果 `instance` 是一个类型为 React `componentClass` 的复合组件 (由 `React.createClass()` 创建)。
|
||||
|
||||
### findAllInRenderedTree
|
||||
|
||||
```javascript
|
||||
array findAllInRenderedTree(
|
||||
ReactComponent tree,
|
||||
function test
|
||||
)
|
||||
```
|
||||
|
||||
遍历 `tree` 里所有的组件,并累积所有 `test(component)` 为 `true` 的组件。它本身并没有什么用,但是它被用作其他测试工具的基本元素。
|
||||
|
||||
### scryRenderedDOMComponentsWithClass
|
||||
|
||||
```javascript
|
||||
array scryRenderedDOMComponentsWithClass(
|
||||
ReactComponent tree, string className
|
||||
)
|
||||
```
|
||||
|
||||
在渲染的树中查找所有 DOM组件的类名匹配`className` 的组件实例。
|
||||
|
||||
### findRenderedDOMComponentWithClass
|
||||
|
||||
```javascript
|
||||
ReactComponent findRenderedDOMComponentWithClass(
|
||||
ReactComponent tree,
|
||||
string className
|
||||
)
|
||||
```
|
||||
|
||||
类似 `scryRenderedDOMComponentsWithClass()` 除了只有一个返回结果,并且要么返回这个结果,要么如果还有其他的匹配项就抛出一个异常。
|
||||
|
||||
### scryRenderedDOMComponentsWithTag
|
||||
|
||||
```javascript
|
||||
array scryRenderedDOMComponentsWithTag(
|
||||
ReactComponent tree,
|
||||
string tagName
|
||||
)
|
||||
```
|
||||
|
||||
在渲染的树中查找所有 DOM 组件的 tag 名匹配 `tagName` 的组件实例。
|
||||
|
||||
### findRenderedDOMComponentWithTag
|
||||
|
||||
```javascript
|
||||
ReactComponent findRenderedDOMComponentWithTag(
|
||||
ReactComponent tree,
|
||||
string tagName
|
||||
)
|
||||
```
|
||||
|
||||
类似 `scryRenderedDOMComponentsWithTag()` 除了只有一个返回结果,并且要么返回这个结果,要么如果还有其他的匹配项就抛出一个异常。
|
||||
|
||||
### scryRenderedComponentsWithType
|
||||
|
||||
```javascript
|
||||
array scryRenderedComponentsWithType(
|
||||
ReactComponent tree,
|
||||
function componentClass
|
||||
)
|
||||
```
|
||||
|
||||
查找所有类型等于 `componentClass` 的组件实例。
|
||||
|
||||
### findRenderedComponentWithType
|
||||
|
||||
```javascript
|
||||
ReactComponent findRenderedComponentWithType(
|
||||
ReactComponent tree, function componentClass
|
||||
)
|
||||
```
|
||||
|
||||
类似 `scryRenderedComponentsWithType()` 除了只有一个返回结果,并且要么返回这个结果,要么如果还有其他的匹配项就抛出一个异常。
|
||||
|
||||
## Shallow rendering(浅渲染)
|
||||
|
||||
浅渲染是一个实验性特性,让你渲染一个组件为 "one level deep" 并且断言渲染方法返回的内容,不用担心子组件的行为,它们没有被实例化或者渲染。这个方式不需要一个 DOM。
|
||||
|
||||
```javascript
|
||||
ReactShallowRenderer createRenderer()
|
||||
```
|
||||
|
||||
在你的测试里调用它来创建一个浅渲染器。你可以把它想做是一个你渲染你要测试的组件的 "地方",它可以自己响应事件并更新。
|
||||
|
||||
```javascript
|
||||
shallowRenderer.render(
|
||||
ReactElement element
|
||||
)
|
||||
```
|
||||
|
||||
类似于 `ReactDOM.render`。
|
||||
|
||||
```javascript
|
||||
ReactElement shallowRenderer.getRenderOutput()
|
||||
```
|
||||
|
||||
在 `render` 被调用后,返回一个浅渲染的输出。你可以接着断言输出的内容。例如,如果你的组件的渲染方法返回:
|
||||
|
||||
```javascript
|
||||
<div>
|
||||
<span className="heading">Title</span>
|
||||
<Subcomponent foo="bar" />
|
||||
</div>
|
||||
```
|
||||
|
||||
然后你可以断言:
|
||||
|
||||
```javascript
|
||||
var renderer = ReactTestUtils.createRenderer();
|
||||
result = renderer.getRenderOutput();
|
||||
expect(result.type).toBe('div');
|
||||
expect(result.props.children).toEqual([
|
||||
<span className="heading">Title</span>,
|
||||
<Subcomponent foo="bar" />
|
||||
]);
|
||||
```
|
||||
|
||||
浅测试现在有一些限制,即不支持 refs。我们在早期发布这个特性,并感激 React 社区关于它应该如何演化的反馈。
|
||||
36
docs/docs/10.5-clone-with-props.zh-CN.md
Normal file
36
docs/docs/10.5-clone-with-props.zh-CN.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
id: clone-with-props-zh-CN
|
||||
title: 克隆 ReactElements
|
||||
permalink: clone-with-props-zh-CN.html
|
||||
prev: test-utils-zh-CN.html
|
||||
next: create-fragment-zh-CN.html
|
||||
---
|
||||
|
||||
> 注意:
|
||||
> `cloneWithProps` 被弃用了. 用 [React.cloneElement](top-level-api.html#react.cloneelement) 代替.
|
||||
|
||||
在很罕见的情况下,你可能需要创建一个 React 元素的拷贝,它与初始的元素有不同的 props。一个例子是克隆这些传递到 `this.props.children` 的元素并用不同的 props 渲染他们。
|
||||
|
||||
```js
|
||||
var cloneWithProps = require('react-addons-clone-with-props');
|
||||
|
||||
var _makeBlue = function(element) {
|
||||
return cloneWithProps(element, {style: {color: 'blue'}});
|
||||
};
|
||||
|
||||
var Blue = React.createClass({
|
||||
render: function() {
|
||||
var blueChildren = React.Children.map(this.props.children, _makeBlue);
|
||||
return <div>{blueChildren}</div>;
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<Blue>
|
||||
<p>This text is blue.</p>
|
||||
</Blue>,
|
||||
document.getElementById('container')
|
||||
);
|
||||
```
|
||||
|
||||
`cloneWithProps` 不传递 `key` 或者 `ref` 到被克隆的元素。`className` 和 `style` props 被自动合并。
|
||||
75
docs/docs/10.6-create-fragment.zh-CN.md
Normal file
75
docs/docs/10.6-create-fragment.zh-CN.md
Normal file
@@ -0,0 +1,75 @@
|
||||
---
|
||||
id: create-fragment-zh-CN
|
||||
title: Keyed Fragments
|
||||
permalink: create-fragment-zh-CN.html
|
||||
prev: clone-with-props-zh-CN.html
|
||||
next: update-zh-CN.html
|
||||
---
|
||||
|
||||
在大多数情况下,你可以使用 `key` prop 指定你从 `render` 返回的元素的 keys。然而,这在一个情况下会失败:如果你有两组你需要记录的子级,将没有办法在不使用包裹元素的情况下放置一个 key 到每组上。
|
||||
|
||||
即是,如果你有一个像这样的组件:
|
||||
|
||||
```js
|
||||
var Swapper = React.createClass({
|
||||
propTypes: {
|
||||
// `leftChildren` and `rightChildren` can be a string, element, array, etc.
|
||||
leftChildren: React.PropTypes.node,
|
||||
rightChildren: React.PropTypes.node,
|
||||
|
||||
swapped: React.PropTypes.bool
|
||||
},
|
||||
render: function() {
|
||||
var children;
|
||||
if (this.props.swapped) {
|
||||
children = [this.props.rightChildren, this.props.leftChildren];
|
||||
} else {
|
||||
children = [this.props.leftChildren, this.props.rightChildren];
|
||||
}
|
||||
return <div>{children}</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
这些子级会在当你改变 `swapped` prop 时加载和卸载,因为没有任何的 key 标记在这两组子级上。
|
||||
|
||||
要解决这个问题,你可以使用 `createFragment` 插件来给予这两组子级 keys.
|
||||
|
||||
#### `Array<ReactNode> createFragment(object children)`
|
||||
|
||||
代替创建数组,我们这样写:
|
||||
|
||||
```js
|
||||
var createFragment = require('react-addons-create-fragment');
|
||||
|
||||
if (this.props.swapped) {
|
||||
children = createFragment({
|
||||
right: this.props.rightChildren,
|
||||
left: this.props.leftChildren
|
||||
});
|
||||
} else {
|
||||
children = createFragment({
|
||||
left: this.props.leftChildren,
|
||||
right: this.props.rightChildren
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
被传入对象的 keys (即 `left` 和 `right`)被用作为整组子级的 keys,并且对象 keys 的顺序被用于决定渲染子级的顺序。通过这个改变,这两个子级将会恰当的在 DOM 里排序,而不被卸载。
|
||||
|
||||
`createFragment` 的返回值应该被对待为一个不透明的对象;你可以使用 `React.Children` 来遍历一个 fragment 但是不应该直接访问它。同样注意,我们依赖于 JavaScript 引擎保留了对象的枚举顺序,这点在 spec 上是不保证的,但是所有主要的浏览器和 VMs 都对非数字键的对象实现了这个特性。
|
||||
|
||||
> **注意:**
|
||||
>
|
||||
> 将来,`createFragment` 也许会被替换为如下的API:
|
||||
>
|
||||
> ```js
|
||||
> return (
|
||||
> <div>
|
||||
> <x:frag key="right">{this.props.rightChildren}</x:frag>,
|
||||
> <x:frag key="left">{this.props.leftChildren}</x:frag>
|
||||
> </div>
|
||||
> );
|
||||
> ```
|
||||
>
|
||||
> 允许你直接在 JSX 里赋值 keys 而不用添加包裹元素。
|
||||
102
docs/docs/10.7-update.zh-CN.md
Normal file
102
docs/docs/10.7-update.zh-CN.md
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
id: update-zh-CN
|
||||
title: immutability 助手
|
||||
permalink: update-zh-CN.html
|
||||
prev: create-fragment-zh-CN.html
|
||||
next: pure-render-mixin-zh-CN.html
|
||||
---
|
||||
|
||||
React 让你可以使用任何你想要的数据管理方式,包括 mutation。然而,如果你可以在你的应用的性能关键性部分里使用 immutable 数据,将会易于实现一个快速的 `shouldComponentUpdate()` 方法来显著加速你的 app。
|
||||
|
||||
在 JavaScript 里处理 immutable 数据比在为此设计的语言中要难的多,比如 [Clojure](http://clojure.org/)。然而,我们提供了一个简单的 immutability 助手,`update()`,它使处理这类数据容易多了,*不用* 根本性的改变你的数据的表达方式。你也同样可以看一看 Facebook 的 [Immutable-js](https://facebook.github.io/immutable-js/docs/) 和[Advanced Performance](/react/docs/advanced-performance.html) 了解更多关于 Immutable-js 的信息。
|
||||
|
||||
## 主要的思路
|
||||
|
||||
如果你像这样变动数据:
|
||||
|
||||
```js
|
||||
myData.x.y.z = 7;
|
||||
// or...
|
||||
myData.a.b.push(9);
|
||||
```
|
||||
|
||||
你将没有任何办法决定哪个数据被改变了,因为之前的拷贝已经被覆盖。作为替代,你需要创建一个新的 `myData` 的拷贝并且只修改需要改变的地方。然后你可以用三个等于在 `shouldComponentUpdate()` 里比较旧的 `myData` 拷贝与新的拷贝:
|
||||
|
||||
```js
|
||||
var newData = deepCopy(myData);
|
||||
newData.x.y.z = 7;
|
||||
newData.a.b.push(9);
|
||||
```
|
||||
|
||||
不幸的是,深拷贝很昂贵,并且有时候不可能。你可以通过仅仅拷贝需要被改变和重用没有改变的对象来缓解这个情况。不幸的是,在当今的 JavaScript 里这会很笨重:
|
||||
|
||||
```js
|
||||
var newData = extend(myData, {
|
||||
x: extend(myData.x, {
|
||||
y: extend(myData.x.y, {z: 7}),
|
||||
}),
|
||||
a: extend(myData.a, {b: myData.a.b.concat(9)})
|
||||
});
|
||||
```
|
||||
|
||||
虽然这相当高性能(因为只对 `log n` 的对象进行了浅拷贝并重用了剩下的),但它写起来很痛苦。看看所有重复的代码!这不仅仅是烦人的,同时也提供了一大片 bugs 区域。
|
||||
|
||||
`update()` 提供了这个模式的简单语法糖来使写这类代码更容易。上面的代码变成:
|
||||
|
||||
```js
|
||||
var update = require('react-addons-update');
|
||||
|
||||
var newData = update(myData, {
|
||||
x: {y: {z: {$set: 7}}},
|
||||
a: {b: {$push: [9]}}
|
||||
});
|
||||
```
|
||||
|
||||
虽然这个语法需要花一些时间来适应(它的灵感来自于 [MongoDB's query language](http://docs.mongodb.org/manual/core/crud-introduction/#query)),但是没有冗余,它可静态分析并且没有 mutative 版本那么多键入。
|
||||
|
||||
`$`-前缀的 keys 被称为 *命令*。被 "变动的" 数据结构被称为 *目标*。
|
||||
|
||||
## 有效的命令
|
||||
|
||||
* `{$push: array}` 在目标上 `push()` 所有 `array` 里的项目。
|
||||
* `{$unshift: array}` 在目标上 `unshift()` 所有 `array` 里的项目。
|
||||
* `{$splice: array of arrays}` 在目标上对于每一个 `arrays` 里的项目使用项目提供的参数调用 `splice()`。
|
||||
* `{$set: any}` 整个替换目标.
|
||||
* `{$merge: object}` 合并 目标和 `object` 的 keys.
|
||||
* `{$apply: function}` 传递当前的值给 function 并用返回值更新它。
|
||||
|
||||
## 例子
|
||||
|
||||
### 简单的 push
|
||||
|
||||
```js
|
||||
var initialArray = [1, 2, 3];
|
||||
var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
|
||||
```
|
||||
`initialArray` is still `[1, 2, 3]`.
|
||||
|
||||
### 嵌套的 collections
|
||||
|
||||
```js
|
||||
var collection = [1, 2, {a: [12, 17, 15]}];
|
||||
var newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
|
||||
// => [1, 2, {a: [12, 13, 14, 15]}]
|
||||
```
|
||||
本例访问了 `collection` 的`2`索引下的键`a`,并且拼接了一个从索引`1`开始(移除`17`)并插入`13`和`14`的项目。
|
||||
|
||||
### 基于当前的值更新新值
|
||||
|
||||
```js
|
||||
var obj = {a: 5, b: 3};
|
||||
var newObj = update(obj, {b: {$apply: function(x) {return x * 2;}}});
|
||||
// => {a: 5, b: 6}
|
||||
// This is equivalent, but gets verbose for deeply nested collections:
|
||||
var newObj2 = update(obj, {b: {$set: obj.b * 2}});
|
||||
```
|
||||
|
||||
### (浅) 合并
|
||||
|
||||
```js
|
||||
var obj = {a: 5, b: 3};
|
||||
var newObj = update(obj, {$merge: {b: 6, c: 7}}); // => {a: 5, b: 6, c: 7}
|
||||
```
|
||||
@@ -21,6 +21,22 @@ React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
Example using ES6 class syntax:
|
||||
|
||||
```js
|
||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||
class FooComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className={this.props.className}>foo</div>;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Under the hood, the mixin implements [shouldComponentUpdate](/react/docs/component-specs.html#updating-shouldcomponentupdate), in which it compares the current props and state with the next ones and returns `false` if the equalities pass.
|
||||
|
||||
> Note:
|
||||
|
||||
46
docs/docs/10.8-pure-render-mixin.zh-CN.md
Normal file
46
docs/docs/10.8-pure-render-mixin.zh-CN.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
id: pure-render-mixin-zh-CN
|
||||
title: PureRenderMixin
|
||||
permalink: pure-render-mixin-zh-CN.html
|
||||
prev: update-zh-CN.html
|
||||
next: perf-zh-CN.html
|
||||
---
|
||||
|
||||
如果你的 React 组件的 render 函数是 "纯净" 的(换句话说,它的渲染在给定相同的 props 和 state 时返回相同的结果),你可以使用这个 mixin 在某些情况下进行性能加速。
|
||||
|
||||
例子:
|
||||
|
||||
```js
|
||||
var PureRenderMixin = require('react-addons-pure-render-mixin');
|
||||
React.createClass({
|
||||
mixins: [PureRenderMixin],
|
||||
|
||||
render: function() {
|
||||
return <div className={this.props.className}>foo</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
使用 ES6 class 语法的例子:
|
||||
|
||||
```js
|
||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||
class FooComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className={this.props.className}>foo</div>;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
在内部, mixin 实现了 [shouldComponentUpdate](/react/docs/component-specs.html#updating-shouldcomponentupdate), 它对当前及下一步的 props 和 state 进行比较,并当相等时返回 `false`。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 它仅仅浅比较对象。如果包含了复杂的对象,可能会对于深层的不同产生 false-negatives。只 mix 到那些含有简单 props 和 state 的组件,或者在你知道深层对象改变时使用 `forceUpdate()` 。或者,考虑使用[immutable objects](https://facebook.github.io/immutable-js/) 来促进快速的嵌套数据比较。
|
||||
>
|
||||
> 此外, `shouldComponentUpdate` 跳过了整个子树的更新。确保所有的子组件都是 "纯净" 的。
|
||||
@@ -3,7 +3,7 @@ id: perf
|
||||
title: Performance Tools
|
||||
permalink: perf.html
|
||||
prev: pure-render-mixin.html
|
||||
next: advanced-performance.html
|
||||
next: shallow-compare.html
|
||||
---
|
||||
|
||||
React is usually quite fast out of the box. However, in situations where you need to squeeze every ounce of performance out of your app, it provides a [shouldComponentUpdate](/react/docs/component-specs.html#updating-shouldcomponentupdate) hook where you can add optimization hints to React's diff algorithm.
|
||||
|
||||
74
docs/docs/10.9-perf.zh-CN.md
Normal file
74
docs/docs/10.9-perf.zh-CN.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
id: perf-zh-CN
|
||||
title: 性能工具
|
||||
permalink: perf-zh-CN.html
|
||||
prev: pure-render-mixin-zh-CN.html
|
||||
next: shallow-compare-zh-CN.html
|
||||
---
|
||||
|
||||
React 通常是相当快的。然而,在你需要压榨你的 app 的每一分性能的情况下,它提供了一个[shouldComponentUpdate](/react/docs/component-specs.html#updating-shouldcomponentupdate) 钩子,在此你可以添加优化提示到 React 的 diff 算法里。
|
||||
|
||||
除了给予你一个你的 app 的整体性能概览外,ReactPerf 还是一个准确告诉你,你需要在哪里放置这些钩子的分析工具。
|
||||
|
||||
## General API
|
||||
|
||||
这里陈述的 `Perf` 对象被用 `require('react-addons-perf')` 暴露,并且只能被使用在 React 的开发模式。你不应在生产环境下在你的 app 包含这个包。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 开发版的 React 慢于生产版,因为所有额外提供的逻辑,例如,React 的友好的控制台警告 (在生产版中被除去)。因此,分析工具仅服务于指示你的 app _相对_ 昂贵的部分。
|
||||
|
||||
### `Perf.start()` and `Perf.stop()`
|
||||
开始/停止测量。其间的React操作被记录用于之后的分析。产生无关紧要时间的操作被忽略。
|
||||
|
||||
在停止以后,你将需要 `Perf.getLastMeasurements()` (下面将介绍)来获取测量结果。
|
||||
|
||||
### `Perf.printInclusive(measurements)`
|
||||
打印总体花费的时间。如果没有传入参数,默认是从上次记录的所有测量数据。它在控制台里打印良好格式化的结果,像这样:
|
||||
|
||||

|
||||
|
||||
### `Perf.printExclusive(measurements)`
|
||||
"独占的"时间不包括花费于加载组件的时间: 处理 props, `getInitialState`, 调用 `componentWillMount` 及 `componentDidMount`, 等等。
|
||||
|
||||

|
||||
|
||||
### `Perf.printWasted(measurements)`
|
||||
|
||||
**分析工具里最有用的部分**.
|
||||
|
||||
"垃圾"时间是花费在组件上实际没有绘制任何东西的时间,例如渲染结果总是相同,所以 DOM 没有被触碰到。
|
||||
|
||||

|
||||
|
||||
### `Perf.printDOM(measurements)`
|
||||
打印底层的 DOM 操纵,例如 "set innerHTML" 和 "remove".
|
||||
|
||||

|
||||
|
||||
## Advanced API
|
||||
|
||||
以上的打印方法使用 `Perf.getLastMeasurements()` 来美观的打印结果。
|
||||
|
||||
### `Perf.getLastMeasurements()`
|
||||
从最后的 start-stop 会话获取测量数据数据。这个数组包含对象,每个看起来像这样:
|
||||
|
||||
```js
|
||||
{
|
||||
// The term "inclusive" and "exclusive" are explained below
|
||||
"exclusive": {},
|
||||
// '.0.0' is the React ID of the node
|
||||
"inclusive": {".0.0": 0.0670000008540228, ".0": 0.3259999939473346},
|
||||
"render": {".0": 0.036999990697950125, ".0.0": 0.010000003385357559},
|
||||
// Number of instances
|
||||
"counts": {".0": 1, ".0.0": 1},
|
||||
// DOM touches
|
||||
"writes": {},
|
||||
// Extra debugging info
|
||||
"displayNames": {
|
||||
".0": {"current": "App", "owner": "<root>"},
|
||||
".0.0": {"current": "Box", "owner": "App"}
|
||||
},
|
||||
"totalTime": 0.48499999684281647
|
||||
}
|
||||
```
|
||||
@@ -2,7 +2,7 @@
|
||||
id: advanced-performance
|
||||
title: Advanced Performance
|
||||
permalink: advanced-performance.html
|
||||
prev: perf.html
|
||||
prev: shallow-compare.html
|
||||
next: context.html
|
||||
---
|
||||
|
||||
|
||||
@@ -160,6 +160,38 @@ function Button(props, context) {
|
||||
Button.contextTypes = {color: React.PropTypes.string};
|
||||
```
|
||||
|
||||
## Updating context
|
||||
|
||||
The `getChildContext` function will be called when the state or props changes. In order to update data in the context, trigger a local state update with `this.setState`. This will trigger a new context and changes will be received by the children.
|
||||
|
||||
```javascript
|
||||
var MediaQuery = React.createClass({
|
||||
getInitialState: function(){
|
||||
return {type:'desktop'};
|
||||
},
|
||||
childContextTypes: {
|
||||
type: React.PropTypes.string
|
||||
},
|
||||
getChildContext: function() {
|
||||
return {type: this.state.type};
|
||||
},
|
||||
componentDidMount: function(){
|
||||
var checkMediaQuery = function(){
|
||||
var type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';
|
||||
if (type !== this.state.type){
|
||||
this.setState({type:type});
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', checkMediaQuery);
|
||||
checkMediaQuery();
|
||||
},
|
||||
render: function(){
|
||||
return this.props.children;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
205
docs/docs/12-context.zh-CN.md
Normal file
205
docs/docs/12-context.zh-CN.md
Normal file
@@ -0,0 +1,205 @@
|
||||
---
|
||||
id: context-zh-CN
|
||||
title: Context
|
||||
permalink: context-zh-CN.html
|
||||
prev: advanced-performance-zh-CN.html
|
||||
---
|
||||
|
||||
React最大的优势之一是很容易从你的React组件里跟踪数据流动。当你看着一个组件,你可以很容易准确看出哪个props被传入,这让你的APP很容易推断。
|
||||
|
||||
偶尔,你想通过组件树传递数据,而不在每一级上手工下传prop,React的 "context" 让你做到这点。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> Context是一个先进的实验性特性.这个 API 很可能在未来版本变化.
|
||||
>
|
||||
> 大多数应用将不会需要用到 context. 尤其是如果你刚开始用React,你很可能不会想用 context.使用 context 将会使你的代码很难理解因为它让数据流不清晰.它类似于在你的应用里使用全局变量传递state.
|
||||
>
|
||||
> **如果你必须使用 context ,保守的使用它**
|
||||
>
|
||||
> 不论你正在创建一个应用或者是库,试着分离你对 context 的使用到一个小区域,并尽可能避免直接使用 context API,以便在API变动时容易升级.
|
||||
|
||||
## 从树里自动传递info
|
||||
|
||||
假设你有一个这样的结构:
|
||||
|
||||
```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>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
在这里例子里,我们手工穿透一个 `color` prop 以便于恰当格式化 `Button` 和 `Message` 组件.主题是一个很好的例子,当你可能想整个子树都可以访问一部分信息时(比如color). 使用 context 我们可以自动传过这个树:
|
||||
|
||||
```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>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
通过添加 `childContextTypes` 和 `getChildContext` 到 `MessageList` ( context 提供),React下传信息到子树中的任何组件(在这个例子中, `Button`可以由定义 `contextTypes`来访问它).
|
||||
|
||||
如果 `contextTypes` 没有定义,那么 `this.context` 将是一个空对象.
|
||||
|
||||
## 父子耦合
|
||||
|
||||
Context 同样可以使你构建这样的 APT:
|
||||
|
||||
```javascript
|
||||
<Menu>
|
||||
<MenuItem>aubergine</MenuItem>
|
||||
<MenuItem>butternut squash</MenuItem>
|
||||
<MenuItem>clementine</MenuItem>
|
||||
</Menu>
|
||||
```
|
||||
|
||||
通过在 `Menu` 组件下传相关的信息,每个 `MenuItem` 可以与包含他们的 `Menu` 组件沟通.
|
||||
|
||||
**在你用这个API构建组件以前,考虑一下是否有清晰的替代方案** 我们 喜欢像这样简单的用数组传递items:
|
||||
|
||||
```javascript
|
||||
<Menu items={['aubergine', 'butternut squash', 'clementine']} />
|
||||
```
|
||||
|
||||
记住你同样可以在props里传递整个React组件,如果你想.
|
||||
|
||||
## 在生命周期方法里引用 context
|
||||
|
||||
如果 `contextTypes` 在一个组件中定义,接下来的生命周期方法会收到一个额外的参数, `context` 对象:
|
||||
|
||||
```javascript
|
||||
void componentWillReceiveProps(
|
||||
object nextProps, object nextContext
|
||||
)
|
||||
|
||||
boolean shouldComponentUpdate(
|
||||
object nextProps, object nextState, object nextContext
|
||||
)
|
||||
|
||||
void componentWillUpdate(
|
||||
object nextProps, object nextState, object nextContext
|
||||
)
|
||||
|
||||
void componentDidUpdate(
|
||||
object prevProps, object prevState, object prevContext
|
||||
)
|
||||
```
|
||||
|
||||
## 在无状态函数组件里引用 context
|
||||
|
||||
无状态函数同样能够引用 `context` 如果 `contextTypes` 被定义为函数的属性.下面的代码展示了被写为无状态函数组件的 `Button` 组件.
|
||||
|
||||
```javascript
|
||||
function Button(props, context) {
|
||||
return (
|
||||
<button style={{'{{'}}background: context.color}}>
|
||||
{props.children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Button.contextTypes = {color: React.PropTypes.string};
|
||||
```
|
||||
|
||||
## Updating context
|
||||
|
||||
当 state 或者 props 变化时 `getChildContext` 函数会被调用。为了更新context里的数据,用 `this.setState` 触发一个本地的state更新。这将会触发一个新的 context 并且子级将收到变化。
|
||||
|
||||
```javascript
|
||||
var MediaQuery = React.createClass({
|
||||
getInitialState: function(){
|
||||
return {type:'desktop'};
|
||||
},
|
||||
childContextTypes: {
|
||||
type: React.PropTypes.string
|
||||
},
|
||||
getChildContext: function() {
|
||||
return {type: this.state.type};
|
||||
},
|
||||
componentDidMount: function(){
|
||||
var checkMediaQuery = function(){
|
||||
var type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';
|
||||
if (type !== this.state.type){
|
||||
this.setState({type:type});
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', checkMediaQuery);
|
||||
checkMediaQuery();
|
||||
},
|
||||
render: function(){
|
||||
return this.props.children;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 什么时候不用 context
|
||||
|
||||
正像全局变量是在写清晰代码时最好要避免的,你应该在大多数情况下避免使用context. 特别是,在用它来"节省输入"和代替显示传入props时要三思.
|
||||
|
||||
context最好的使用场景是隐式的传入登录的用户,当前的语言,或者主题信息.要不然所有这些可能就是全局变量,但是context让你限定他们到一个单独的React树里.
|
||||
|
||||
不要用context在组件里传递你的模型数据.通过树显示的传递你的数据更容易理解.使用context使你的组件更耦合和不可复用,因为 依赖于他们在哪里渲染,他们会表现不同的行为.
|
||||
|
||||
## 已知的限制
|
||||
|
||||
如果一个由组件提供的context值变动,使用那个值的子级不会更新,如果一个直接的父级从 `shouldComponentUpdate` 返回 `false` .详见 issue [#2517](https://github.com/facebook/react/issues/2517) .
|
||||
@@ -1,9 +1,5 @@
|
||||
---
|
||||
id: complementary-tools-it-IT
|
||||
title: Strumenti Complementari
|
||||
permalink: complementary-tools-it-IT.html
|
||||
prev: videos-it-IT.html
|
||||
next: examples-it-IT.html
|
||||
layout: redirect
|
||||
dest_url: https://github.com/facebook/react/wiki/Complementary-Tools
|
||||
---
|
||||
|
||||
Questa pagina è stata spostata sul [wiki di GitHub](https://github.com/facebook/react/wiki/Complementary-Tools).
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
---
|
||||
id: complementary-tools-ko-KR
|
||||
title: 상호 보완적인 도구들
|
||||
permalink: complementary-tools-ko-KR.html
|
||||
prev: videos-ko-KR.html
|
||||
next: examples-ko-KR.html
|
||||
layout: redirect
|
||||
dest_url: https://github.com/facebook/react/wiki/Complementary-Tools
|
||||
---
|
||||
|
||||
이 페이지는 이동되었습니다. [GitHub wiki](https://github.com/facebook/react/wiki/Complementary-Tools).
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
---
|
||||
id: complementary-tools
|
||||
title: Complementary Tools
|
||||
permalink: complementary-tools.html
|
||||
prev: videos.html
|
||||
next: examples.html
|
||||
layout: redirect
|
||||
dest_url: https://github.com/facebook/react/wiki/Complementary-Tools
|
||||
---
|
||||
|
||||
This page has moved to the [GitHub wiki](https://github.com/facebook/react/wiki/Complementary-Tools).
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
---
|
||||
id: complementary-tools-zh-CN
|
||||
title: 补充工具
|
||||
permalink: complementary-tools-zh-CN.html
|
||||
prev: videos-zh-CN.html
|
||||
next: examples-zh-CN.html
|
||||
layout: redirect
|
||||
dest_url: https://github.com/facebook/react/wiki/Complementary-Tools
|
||||
---
|
||||
|
||||
本页被移到了 [GitHub wiki](https://github.com/facebook/react/wiki/Complementary-Tools)。
|
||||
|
||||
29
docs/docs/conferences.zh-CN.md
Normal file
29
docs/docs/conferences.zh-CN.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
id: conferences-zh-CN
|
||||
title: 会议
|
||||
permalink: conferences-zh-CN.html
|
||||
prev: thinking-in-react-zh-CN.html
|
||||
next: videos-zh-CN.html
|
||||
---
|
||||
|
||||
### React.js Conf 2015
|
||||
一月 28 & 29
|
||||
|
||||
[Website](http://conf.reactjs.com/) - [Schedule](http://conf.reactjs.com/schedule.html) - [Videos](https://www.youtube-nocookie.com/playlist?list=PLb0IAmt7-GS1cbw4qonlQztYV1TAW0sCr)
|
||||
|
||||
<iframe width="650" height="315" src="//www.youtube-nocookie.com/embed/KVZ-P-ZI6W4?list=PLb0IAmt7-GS1cbw4qonlQztYV1TAW0sCr" frameborder="0" allowfullscreen></iframe>
|
||||
|
||||
### ReactEurope 2015
|
||||
七月 2 & 3
|
||||
|
||||
[Website](http://www.react-europe.org/) - [Schedule](http://www.react-europe.org/#schedule)
|
||||
|
||||
### Reactive 2015
|
||||
十一月 2-4
|
||||
|
||||
[Website](https://reactive2015.com/) - [Schedule](https://reactive2015.com/schedule_speakers.html#schedule)
|
||||
|
||||
### ReactEurope 2016
|
||||
六月 2 & 3
|
||||
|
||||
[Website](http://www.react-europe.org/) - [Schedule](http://www.react-europe.org/#schedule)
|
||||
@@ -1,8 +1,5 @@
|
||||
---
|
||||
id: examples-it-IT
|
||||
title: Esempi
|
||||
permalink: examples-it-IT.html
|
||||
prev: complementary-tools-it-IT.html
|
||||
layout: redirect
|
||||
dest_url: https://github.com/facebook/react/wiki/Examples
|
||||
---
|
||||
|
||||
Questa pagina è stata spostata sul [wiki di GitHub](https://github.com/facebook/react/wiki/Examples).
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
---
|
||||
id: examples-ko-KR
|
||||
title: 예제들
|
||||
permalink: examples-ko-KR.html
|
||||
prev: complementary-tools-ko-KR.html
|
||||
layout: redirect
|
||||
dest_url: https://github.com/facebook/react/wiki/Examples
|
||||
---
|
||||
|
||||
이 페이지는 이동되었습니다. [GitHub wiki](https://github.com/facebook/react/wiki/Examples).
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
---
|
||||
id: examples
|
||||
title: Examples
|
||||
permalink: examples.html
|
||||
prev: complementary-tools.html
|
||||
layout: redirect
|
||||
dest_url: https://github.com/facebook/react/wiki/Examples
|
||||
---
|
||||
|
||||
This page has moved to the [GitHub wiki](https://github.com/facebook/react/wiki/Examples).
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
---
|
||||
id: examples-zh-CN
|
||||
title: 示例
|
||||
permalink: examples-zh-CN.html
|
||||
prev: complementary-tools-zh-CN.html
|
||||
layout: redirect
|
||||
dest_url: https://github.com/facebook/react/wiki/Examples
|
||||
---
|
||||
|
||||
本页被移到了 [GitHub wiki](https://github.com/facebook/react/wiki/Examples)。
|
||||
|
||||
@@ -27,17 +27,33 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
To install React DOM and build your bundle after installing browserify:
|
||||
To install React DOM and build your bundle with browserify:
|
||||
|
||||
```sh
|
||||
$ npm install --save react react-dom babelify babel-preset-react
|
||||
$ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
|
||||
```
|
||||
|
||||
To install React DOM and build your bundle with webpack:
|
||||
|
||||
```sh
|
||||
$ npm install --save react react-dom babel-preset-react
|
||||
$ webpack
|
||||
```
|
||||
|
||||
> Note:
|
||||
>
|
||||
> If you are using ES2015, you will want to also use the `babel-preset-es2015` package.
|
||||
|
||||
**Note:** by default, React will be in development mode, which is slower, and not advised for production. To use React in production mode, set the environment variable `NODE_ENV` to `production` (using envify or webpack's DefinePlugin). For example:
|
||||
|
||||
```js
|
||||
new webpack.DefinePlugin({
|
||||
"process.env": {
|
||||
NODE_ENV: JSON.stringify("production")
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Quick Start Without npm
|
||||
|
||||
@@ -73,7 +89,7 @@ In the root directory of the starter kit, create a `helloworld.html` with the fo
|
||||
</html>
|
||||
```
|
||||
|
||||
The XML syntax inside of JavaScript is called JSX; check out the [JSX syntax](/react/docs/jsx-in-depth.html) to learn more about it. In order to translate it to vanilla JavaScript we use `<script type="text/babel">` and include Babel to actually perform the transformation in the browser.
|
||||
The XML syntax inside of JavaScript is called JSX; check out the [JSX syntax](/react/docs/jsx-in-depth.html) to learn more about it. In order to translate it to vanilla JavaScript we use `<script type="text/babel">` and include Babel to actually perform the transformation in the browser. Open the html from a browser and you should already be able to see the greeting!
|
||||
|
||||
### Separate File
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ redirect_from: "docs/index-zh-CN.html"
|
||||
* **[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 包.
|
||||
@@ -29,23 +28,41 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
在安装 browserify 之后安装 React DOM 和构建你的应用包。
|
||||
要用 browserify 安装 React DOM 和构建你的包。
|
||||
|
||||
```sh
|
||||
$ npm install --save react react-dom
|
||||
$ browserify -t babelify main.js -o bundle.js
|
||||
$ npm install --save react react-dom babelify babel-preset-react
|
||||
$ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
|
||||
```
|
||||
|
||||
## 不使用 npm 快速开始
|
||||
要用 webpack 安装 React DOM 和构建你的包:
|
||||
|
||||
```sh
|
||||
$ npm install --save react react-dom babel-preset-react
|
||||
$ webpack
|
||||
```
|
||||
|
||||
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 预生成包的入门教程包。
|
||||
> 注意:
|
||||
>
|
||||
> 如果你正在使用 ES2015, 你将要使用 `babel-preset-es2015` 包.
|
||||
|
||||
**注意:** 默认情况下,React 将会在开发模式,很缓慢,不建议用于生产。要在生产模式下使用 React,设置环境变量 `NODE_ENV` 为 `production` (使用 envify 或者 webpack's DefinePlugin)。例如:
|
||||
|
||||
```js
|
||||
new webpack.DefinePlugin({
|
||||
"process.env": {
|
||||
NODE_ENV: JSON.stringify("production")
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 不用 npm 的快速开始
|
||||
|
||||
如果你现在还没准备要使用npm,你可以下载这个已经包含了预构建的 React 和 React DOM 拷贝的入门套件.
|
||||
|
||||
<div class="buttons-unit downloads">
|
||||
<a href="/react/downloads/react-{{site.react_version}}.zip" class="button">
|
||||
下载入门教程 {{site.react_version}}
|
||||
下载入门套件 {{site.react_version}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -73,7 +90,7 @@ If you're not ready to use npm yet, you can download the starter kit which inclu
|
||||
</html>
|
||||
```
|
||||
|
||||
在 JavaScript 代码里写着 XML 格式的代码称为 JSX;可以去 [JSX 语法](/react/docs/jsx-in-depth.html) 里学习更多 JSX 相关的知识。为了把 JSX 转成标准的 JavaScript,我们用 `<script type="text/babel">` 标签,并引入 Babel 来完成在浏览器里的代码转换。
|
||||
在 JavaScript 代码里写着 XML 格式的代码称为 JSX;可以去 [JSX 语法](/react/docs/jsx-in-depth.html) 里学习更多 JSX 相关的知识。为了把 JSX 转成标准的 JavaScript,我们用 `<script type="text/babel">` 标签,并引入 Babel 来完成在浏览器里的代码转换。在浏览器里打开这个html,你应该可以看到成功的消息!
|
||||
|
||||
### 分离文件
|
||||
|
||||
@@ -96,21 +113,24 @@ ReactDOM.render(
|
||||
|
||||
### 离线转换
|
||||
|
||||
先安装[Babel](http://babeljs.io/)命令行工具(依赖 [npm](https://www.npmjs.com/)):
|
||||
先安装[Babel](http://babeljs.io/)命令行工具(需要 [npm](https://www.npmjs.com/)):
|
||||
|
||||
```
|
||||
npm install --global babel
|
||||
npm install --global babel-cli
|
||||
npm install babel-preset-react
|
||||
```
|
||||
|
||||
然后把你的 `src/helloworld.js` 文件转成标准的 JavaScript:
|
||||
|
||||
```
|
||||
babel src --watch --out-dir build
|
||||
|
||||
babel --presets react src --watch --out-dir build
|
||||
```
|
||||
|
||||
`build/helloworld.js` 会在你对文件进行修改时自动生成。 阅读 [Babel CLI 文档](http://babeljs.io/docs/usage/cli/) 了解高级用法。
|
||||
> 注意:
|
||||
>
|
||||
> 如果你正在使用 ES2015, 你将需要使用 `babel-preset-es2015` 包.
|
||||
|
||||
`build/helloworld.js` 会在你对文件进行修改时自动生成。 阅读 [Babel CLI 文档](http://babeljs.io/docs/usage/cli/) 了解高级用法。
|
||||
|
||||
```javascript{2}
|
||||
ReactDOM.render(
|
||||
@@ -119,16 +139,18 @@ 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>
|
||||
<!-- 不需要 Babel! -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
@@ -137,8 +159,6 @@ ReactDOM.render(
|
||||
</html>
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 下一步
|
||||
|
||||
去看看[入门教程](/react/docs/tutorial.html) 和入门教程包 `examples` 目录下的其它例子学习更多。
|
||||
|
||||
@@ -66,9 +66,7 @@ factoryFunction createFactory(
|
||||
)
|
||||
```
|
||||
|
||||
Return a function that produces ReactElements of a given type. Like `React.createElement`,
|
||||
the type argument can be either an html tag name string (eg. 'div', 'span', etc), or a
|
||||
`ReactClass`.
|
||||
Return a function that produces ReactElements of a given type. Like `React.createElement`, the type argument can be either an html tag name string (eg. 'div', 'span', etc), or a `ReactClass`.
|
||||
|
||||
|
||||
### React.isValidElement
|
||||
|
||||
@@ -69,64 +69,6 @@ factoryFunction createFactory(
|
||||
返回一个生成给定类型的 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
|
||||
@@ -136,14 +78,6 @@ 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!')`。
|
||||
@@ -161,10 +95,10 @@ DOMElement findDOMNode(ReactComponent component)
|
||||
#### React.Children.map
|
||||
|
||||
```javascript
|
||||
object React.Children.map(object children, function fn [, object thisArg])
|
||||
array React.Children.map(object children, function fn [, object thisArg])
|
||||
```
|
||||
|
||||
在每一个包含在 `children` 中的直接子级上调用 `fn` ,`fn`中的 `this` 设置为 `thisArg`。如果 `children` 是一个嵌套的对象或者数组,它将被遍历:不会传入容器对象到 `fn` 中。如果 children 是 `null` 或者 `undefined`,则返回 `null` 或者 `undefined` 而不是一个空对象。
|
||||
在每一个包含在 `children` 中的直接子级上调用 `fn` ,`fn`中的 `this` 设置为 `thisArg`。如果 `children` 是一个嵌套的对象或者数组,它将被遍历:不会传入容器对象到 `fn` 中。如果 children 是 `null` 或者 `undefined`,则返回 `null` 或者 `undefined` 而不是一个空数组。
|
||||
|
||||
#### React.Children.forEach
|
||||
|
||||
@@ -172,7 +106,7 @@ object React.Children.map(object children, function fn [, object thisArg])
|
||||
React.Children.forEach(object children, function fn [, object thisArg])
|
||||
```
|
||||
|
||||
类似 `React.Children.map()`,但是不返回对象。
|
||||
类似 `React.Children.map()`,但是不返回数组。
|
||||
|
||||
#### React.Children.count
|
||||
|
||||
@@ -189,3 +123,89 @@ object React.Children.only(object children)
|
||||
```
|
||||
|
||||
返回 `children` 中仅有的子级。否则抛出异常。
|
||||
|
||||
#### React.Children.toArray
|
||||
|
||||
```javascript
|
||||
array React.Children.toArray(object children)
|
||||
```
|
||||
|
||||
以赋key给每个child的平坦的数组形式,返回不透明的 `children` 数据结构.如果你想操纵你的渲染方法的子级的合集这很有用,尤其如果你想在 `this.props.children` 传下之前渲染或者切割.
|
||||
|
||||
## ReactDOM
|
||||
|
||||
`react-dom` 包提供了 具体的DOM方法,这些方法可以在你的app的顶层作为一个你需要时脱离React模式的安全舱口 被使用.你的大多数组件不需要使用这个模块.
|
||||
|
||||
### ReactDOM.render
|
||||
|
||||
```javascript
|
||||
ReactComponent render(
|
||||
ReactElement element,
|
||||
DOMElement container,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
渲染一个 ReactElement 到 DOM 里提供的 `容器(container)`中,并返回一个对 组件(或者返回 `null` 对于 [无状态组件](/react/docs/reusable-components.html#stateless-functions)) 的[引用](/react/docs/more-about-refs.html)
|
||||
|
||||
如果 ReactElement 之前被渲染到了 `container` 中,这将对它执行一次更新,并仅变动需要变动的 DOM 来反映最新的 React 组件。
|
||||
|
||||
如果提供了可选的回调函数,则该函数将会在组件渲染或者更新之后被执行。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> `ReactDOM.render()` 控制你传入的 container 节点的内容。
|
||||
> 当初次调用时,任何现存于内的 DOM 元素将被替换。
|
||||
> 其后的调用使用 React的 diffing 算法来有效率的更新。
|
||||
>
|
||||
> `ReactDOM.render()` 不会修改 container 节点(只修改 container 的子级)。
|
||||
> 将来,也许能够直接插入一个组件到已经存在的 DOM 节点而不覆盖
|
||||
> 现有的子级。
|
||||
|
||||
|
||||
### ReactDOM.unmountComponentAtNode
|
||||
|
||||
```javascript
|
||||
boolean unmountComponentAtNode(DOMElement container)
|
||||
```
|
||||
|
||||
从 DOM 中移除已经挂载的 React 组件,并清除它的事件处理器和 state。如果在 container 中没有组件被挂载,调用此函数将什么都不做。如果组件被卸载返回 `true`,如果没有组件被卸载返回 `false`。
|
||||
|
||||
|
||||
### ReactDOM.findDOMNode
|
||||
|
||||
```javascript
|
||||
DOMElement findDOMNode(ReactComponent component)
|
||||
```
|
||||
如果这个组件已经被挂载到了 DOM,它返回相应的浏览器原生的 DOM 元素。这个方法对于读取 DOM 的值很有用,比如表单域的值和执行 DOM 的测量。**在大多数情况下,你可以连接一个ref到DOM节点上,并避免使用 `findDOMNode`** 如果 `render` 返回 `null` 或者 `false`, `findDOMNode` 返回 `null`.
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> `findDOMNode()` 是一个用来访问底层DOM节点的安全舱口.大多数情况下,使用这个安全舱口是不被鼓励的,因为它穿破了组件的抽象.
|
||||
>
|
||||
> `findDOMNode()` 只在已挂载的组件上工作(即是,已经被放置到DOM里的组件).如果你尝试在没有被挂载的组件上调用这个方法(比如在 一个没有被创建的组件的`render()`里 调用 `findDOMNode()` )会抛出一个异常.
|
||||
>
|
||||
> `findDOMNode()` 不能用在无状态组件.
|
||||
|
||||
## ReactDOMServer
|
||||
|
||||
`react-dom/server` 允许你在服务器上渲染你的组件.
|
||||
|
||||
### ReactDOMServer.renderToString
|
||||
|
||||
```javascript
|
||||
string renderToString(ReactElement element)
|
||||
```
|
||||
|
||||
把 ReactElement 渲染为它原始的 HTML 。这应该仅在服务器端使用。React 将会返回一个 HTML 字符串。你可以用这种方法在服务器端生成 HTML,然后在初始请求下传这些标记,以获得更快的页面加载速度及允许搜索引擎抓取页面(便于 SEO)。
|
||||
|
||||
如果在一个在已经有了这种服务器预渲染标记的节点上面调用 `ReactDOM.render()`,React 将会维护该节点,仅绑定事件处理器,让你有一个非常高效的初次加载体验。
|
||||
|
||||
|
||||
### ReactDOMServer.renderToStaticMarkup
|
||||
|
||||
```javascript
|
||||
string renderToStaticMarkup(ReactElement element)
|
||||
```
|
||||
|
||||
类似于 `renderToString` ,除了不创建额外的 DOM 属性,比如 `data-react-id`,这仅在 React 内部使用的属性。如果你想用 React 做一个简单的静态页面生成器,这是很有用的,因为去除额外的属性能够节省很多字节。
|
||||
|
||||
@@ -106,7 +106,7 @@ boolean isMounted()
|
||||
|
||||
> Note:
|
||||
>
|
||||
> This method is not available on ES6 `class` components that extend `React.Component`. It may be removed entirely in a future version of React.
|
||||
> This method is not available on ES6 `class` components that extend `React.Component`. It will likely be removed entirely in a future version of React, so you might as well [start migrating away from isMounted() now](/react/blog/2015/12/16/ismounted-antipattern.html).
|
||||
|
||||
|
||||
### setProps
|
||||
@@ -124,11 +124,11 @@ Calling `setProps()` on a root-level component will change its properties and tr
|
||||
|
||||
> Note:
|
||||
>
|
||||
> This method is deprecated and will be removed soon. This method is not available on ES6 `class` components that extend `React.Component`. Instead of calling `setProps`, try invoking ReactDOM.render() again with the new props. For additional notes, see our [blog post about using the Top Level API](/react/blog/2015/10/01/react-render-and-top-level-api.html)
|
||||
>
|
||||
> When possible, the declarative approach of calling `ReactDOM.render()` again on the same node is preferred instead. It tends to make updates easier to reason about. (There's no significant performance difference between the two approaches.)
|
||||
>
|
||||
> This method can only be called on a root-level component. That is, it's only available on the component passed directly to `ReactDOM.render()` and none of its children. If you're inclined to use `setProps()` on a child component, instead take advantage of reactive updates and pass the new prop to the child component when it's created in `render()`.
|
||||
>
|
||||
> This method is not available on ES6 `class` components that extend `React.Component`. It may be removed entirely in a future version of React.
|
||||
|
||||
### replaceProps
|
||||
|
||||
@@ -143,4 +143,4 @@ Like `setProps()` but deletes any pre-existing props instead of merging the two
|
||||
|
||||
> Note:
|
||||
>
|
||||
> This method is not available on ES6 `class` components that extend `React.Component`. It may be removed entirely in a future version of React.
|
||||
> This method is deprecated and will be removed soon. This method is not available on ES6 `class` components that extend `React.Component`. Instead of calling `replaceProps`, try invoking ReactDOM.render() again with the new props. For additional notes, see our [blog post about using the Top Level API](/react/blog/2015/10/01/react-render-and-top-level-api.html)
|
||||
|
||||
@@ -8,13 +8,13 @@ next: component-specs-zh-CN.html
|
||||
|
||||
## React.Component
|
||||
|
||||
当渲染时,React 组件的实例在 React 内部被创建。这些实例在随后的渲染中被重复使用,并可以在组件方法中通过 `this` 访问。唯一的在 React 之外获取 React 组件实例句柄的方法是保存 `React.render` 的返回值。在其它组件内,你可以使用 [refs](/react/docs/more-about-refs-zh-CN.html) 得到相同的结果。
|
||||
当渲染时,React 组件的实例在 React 内部被创建。这些实例在随后的渲染中被重复使用,并可以在组件方法中通过 `this` 访问。唯一的在 React 之外获取 React 组件实例句柄的方法是保存 `ReactDOM.render` 的返回值。在其它组件内,你可以使用 [refs](/react/docs/more-about-refs-zh-CN.html) 得到相同的结果。
|
||||
|
||||
|
||||
### setState
|
||||
|
||||
```javascript
|
||||
setState(
|
||||
void setState(
|
||||
function|object nextState,
|
||||
[function callback]
|
||||
)
|
||||
@@ -29,7 +29,7 @@ setState(
|
||||
setState({mykey: 'my new value'});
|
||||
```
|
||||
|
||||
也可以以 `function(state, props)` 传递一个函数。当你想要把一个在设置任何值之前参考前一次 state+props 的值的原子更新放在队列中 这会有很用。例如,假如我们想在 state 增加一个值。
|
||||
也可以以 `function(state, props)` 传递一个函数。当你想要把一个在设置任何值之前参考前一次 state+props 的值的原子更新放在队列中 这会有很用。例如,假如我们想在 state 增加一个值:
|
||||
|
||||
```javascript
|
||||
setState(function(previousState, currentProps) {
|
||||
@@ -53,7 +53,7 @@ setState(function(previousState, currentProps) {
|
||||
### replaceState
|
||||
|
||||
```javascript
|
||||
replaceState(
|
||||
void replaceState(
|
||||
object nextState,
|
||||
[function callback]
|
||||
)
|
||||
@@ -69,7 +69,7 @@ replaceState(
|
||||
### forceUpdate
|
||||
|
||||
```javascript
|
||||
forceUpdate(
|
||||
void forceUpdate(
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
@@ -91,7 +91,7 @@ DOMElement getDOMNode()
|
||||
|
||||
> Note:
|
||||
>
|
||||
> getDOMNode 被废弃了,已经被 [React.findDOMNode()] 替换(/react/docs/top-level-api-zh-CN.html#react.finddomnode).
|
||||
> getDOMNode 被废弃了,已经被 [ReactDOM.findDOMNode()] 替换(/react/docs/top-level-api-zh-CN.html#reactdom.finddomnode).
|
||||
>
|
||||
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。它也许会在未来的 React 版本中被完全移除。
|
||||
|
||||
@@ -99,41 +99,41 @@ DOMElement getDOMNode()
|
||||
### isMounted
|
||||
|
||||
```javascript
|
||||
bool isMounted()
|
||||
boolean isMounted()
|
||||
```
|
||||
|
||||
如果组件渲染到了 DOM 中,`isMounted()` 返回 true,否则返回 `false`。可以使用该方法来控制对 `setState()` 和 `forceUpdate()` 的异步调用。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。它也许会在未来的 React 版本中被完全移除。
|
||||
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。它也许会在未来的 React 版本中被完全移除,所以你也要移除它 [start migrating away from isMounted() now](/react/blog/2015/12/16/ismounted-antipattern.html)
|
||||
|
||||
|
||||
### setProps
|
||||
|
||||
```javascript
|
||||
setProps(
|
||||
void setProps(
|
||||
object nextProps,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
当和一个外部的 JavaScript 应用整合的时候,你也许会想用 `React.render()` 给 React 组件标示一个改变。
|
||||
当和一个外部的 JavaScript 应用整合的时候,你也许会想用 `ReactDOM.render()` 给 React 组件标示一个改变。
|
||||
|
||||
在根组件上调用 `setProps()` 会改变他的属性并触发一次重绘。另外,你可以提供一个可选的回调函数,一旦 `setProps` 完成并且组件被重绘它就执行。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 如果可能,上述的在同一个节点上再次调用 `React.render()` 的方法是优先替代的。它往往使更新更容易理解。(两种方法并没有显著的性能区别。)
|
||||
> 这个方法被弃用了并会很快移除.这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用. 取代调用 `setProps`,试着以新的 props 再次调用 `ReactDOM.render()`. 更多的注意事项,见我们的[blog post about using the Top Level API](/react/blog/2015/10/01/react-render-and-top-level-api.html)
|
||||
>
|
||||
> 这个方法仅能在根组件上被调用。也就是说,它仅在直接传给 `React.render()` 的组件上可用,在它的子级上不可用。如果你倾向于在子组件上使用 `setProps()`,不要利用响应式更新,而是当子组件在 `render()` 中创建的时候传入新的 prop 到子组件中。
|
||||
> 如果可能,上述的在同一个节点上再次调用 `ReactDOM.render()` 的方法是优先替代的。它往往使更新更容易理解。(两种方法并没有显著的性能区别。)
|
||||
>
|
||||
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。它也许会在未来的 React 版本中被完全移除。
|
||||
> 这个方法仅能在根组件上被调用。也就是说,它仅在直接传给 `ReactDOM.render()` 的组件上可用,在它的子级上不可用。如果你倾向于在子组件上使用 `setProps()`,不要利用响应式更新,而是当子组件在 `render()` 中创建的时候传入新的 prop 到子组件中。
|
||||
|
||||
### replaceProps
|
||||
|
||||
```javascript
|
||||
replaceProps(
|
||||
void replaceProps(
|
||||
object nextProps,
|
||||
[function callback]
|
||||
)
|
||||
@@ -143,4 +143,4 @@ replaceProps(
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。它也许会在未来的 React 版本中被完全移除。
|
||||
> 这个方法被弃用了并会很快移除.这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用. 取代调用 `replaceProps`,试着以新的 props 再次调用 `ReactDOM.render()`. 更多的注意事项,见我们的[blog post about using the Top Level API](/react/blog/2015/10/01/react-render-and-top-level-api.html)
|
||||
|
||||
@@ -148,6 +148,8 @@ componentWillReceiveProps: function(nextProps) {
|
||||
|
||||
> Note:
|
||||
>
|
||||
> One common mistake is for code executed during this lifecycle method to assume that props have changed. To understand why this is invalid, read [A implies B does not imply B implies A](/react/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html)
|
||||
>
|
||||
> There is no analogous method `componentWillReceiveState`. An incoming prop transition may cause a state change, but the opposite is not true. If you need to perform operations in response to a state change, use `componentWillUpdate`.
|
||||
|
||||
|
||||
@@ -161,8 +163,7 @@ boolean shouldComponentUpdate(
|
||||
|
||||
Invoked before rendering when new props or state are being received. This method is not called for the initial render or when `forceUpdate` is used.
|
||||
|
||||
Use this as an opportunity to `return false` when you're certain that the
|
||||
transition to the new props and state will not require a component update.
|
||||
Use this as an opportunity to `return false` when you're certain that the transition to the new props and state will not require a component update.
|
||||
|
||||
```javascript
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
|
||||
217
docs/docs/ref-03-component-specs.zh-CN.md
Normal file
217
docs/docs/ref-03-component-specs.zh-CN.md
Normal file
@@ -0,0 +1,217 @@
|
||||
---
|
||||
id: component-specs-zh-CN
|
||||
title: 组件的规范和生命周期
|
||||
permalink: component-specs-zh-CN.html
|
||||
prev: component-api-zh-CN.html
|
||||
next: tags-and-attributes-zh-CN.html
|
||||
---
|
||||
|
||||
## 组件规范(Specifications)
|
||||
|
||||
当调用 `React.createClass()` 创建一个组件类时,你应该提供一个包含有 `render` 方法以及可选的其他生命周期方法的 规范(Specifications)对象.
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 同样可以使用单纯的 JavaScript 类作为组件类. 这些类可以实现大多数相同的方法,虽然有一些不同.更多关于不同的信息,请阅读我们关于[ES6 classes](/react/docs/reusable-components.html#es6-classes)的文档.
|
||||
|
||||
### render
|
||||
|
||||
```javascript
|
||||
ReactElement render()
|
||||
```
|
||||
|
||||
`render()` 是必须的
|
||||
|
||||
当被调用时,它应该检查 `this.props` 和 `this.state` 并返回单个子元素.这个子元素即可以是一个 对原生DOM的虚拟表达(比如 `<div />` 或 `React.DOM.div()`)也可以是其他你自定义的复合组件.
|
||||
|
||||
你也可以返回 `null` 或 `false` 来指示你不想要任何东西被渲染.幕后,React 渲染一个 `<noscript>` tag 来与我们当前的diffing算法协同工作.当返回 `null` 或 `false` ,`ReactDOM.findDOMNode(this)` 会返回 `null`.
|
||||
|
||||
`render()` 函数应该是纯净的,意味着它不改变组件的状态,它在每次调用时返回相同的结果,并且它不读和写 DOM 或者其他方式与浏览器互动(例如,使用 `setTimeout`).如果你需要与浏览器互动,在 `componentDidMount()` 里执行你的工作,或者其他生命周期方法里.保持 `render()` 纯净使服务器渲染更实用并且让组件更容易被思考.
|
||||
|
||||
|
||||
### getInitialState
|
||||
|
||||
```javascript
|
||||
object getInitialState()
|
||||
```
|
||||
|
||||
当组件被挂载时调用一次.返回值会被用作为 `this.state` 的初始值.
|
||||
|
||||
|
||||
### getDefaultProps
|
||||
|
||||
```javascript
|
||||
object getDefaultProps()
|
||||
```
|
||||
|
||||
在类被创建时调用一次并被缓存.在这个mapping里的值会被设置给 `this.props` 如果父组件没有指定对应的 prop (例如 使用一个 `in` 检查).
|
||||
|
||||
这个方法在任何实例被创建之前调用,因此不能依赖于 `this.props`.另外,小心,任何被 `getDefaultProps()`返回的复杂对象会被跨实例共享,而不是被拷贝.
|
||||
|
||||
|
||||
### propTypes
|
||||
|
||||
```javascript
|
||||
object propTypes
|
||||
```
|
||||
|
||||
`propTypes` 对象允许你验证传递到你的组建的 props.更多关于 `propTypes` 的信息,见 [Reusable Components](/react/docs/reusable-components.html).
|
||||
|
||||
|
||||
### mixins
|
||||
|
||||
```javascript
|
||||
array mixins
|
||||
```
|
||||
|
||||
`mixins` 数组允许你用 mixins 来在多个组件间共享行为.更多关于 mixins 的信息,见 [Reusable Components](/react/docs/reusable-components.html).
|
||||
|
||||
|
||||
### statics
|
||||
|
||||
```javascript
|
||||
object statics
|
||||
```
|
||||
|
||||
`statics` 对象允许你定义可以在组件类上调用的静态方法.例如:
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
statics: {
|
||||
customMethod: function(foo) {
|
||||
return foo === 'bar';
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
});
|
||||
|
||||
MyComponent.customMethod('bar'); // true
|
||||
```
|
||||
|
||||
在这个块里定义的方法是 _static_,意味着你可以在任何组件实例被创建前运行他们,并且这些方法没有对你组件的 props 或 state 的访问权.如果你在静态方法里检查props的值,把调用者作为参数传入props给静态函数.
|
||||
|
||||
|
||||
### displayName
|
||||
|
||||
```javascript
|
||||
string displayName
|
||||
```
|
||||
|
||||
`displayName` 字符串被用在调试信息.JSX 自动设置这个值;见 [JSX in Depth](/react/docs/jsx-in-depth.html#the-transform).
|
||||
|
||||
|
||||
## Lifecycle Methods
|
||||
|
||||
多种方法在组件生命周期的特定点上被执行.
|
||||
|
||||
|
||||
### Mounting: componentWillMount
|
||||
|
||||
```javascript
|
||||
void componentWillMount()
|
||||
```
|
||||
|
||||
被调用一次,即在客户端也在服务端,在最初的渲染发生之前 立即被调用.如果你在这个方法里调用 `setState` , `render()` 将会看到更新的 state 并不论state的变化只执行一次.
|
||||
|
||||
|
||||
### Mounting: componentDidMount
|
||||
|
||||
```javascript
|
||||
void componentDidMount()
|
||||
```
|
||||
|
||||
被调用一次,只在客户端(不在服务端),在最初的渲染发生之后 立即被调用.在生命周期的这个点上,你可以访问任何对你的子级的refs (比如 访问底层的DOM表达).子组件的 `componentDidMount()` 方法在父组件之前被调用.
|
||||
|
||||
如果你想与其他 JavaScript 框架整合,用 `setTimeout` 或 `setInterval` 设置timers,或者发送 AJAX 请求,执行这些操作在此方法中.
|
||||
|
||||
|
||||
### Updating: componentWillReceiveProps
|
||||
|
||||
```javascript
|
||||
void componentWillReceiveProps(
|
||||
object nextProps
|
||||
)
|
||||
```
|
||||
|
||||
当一个组件收到新的props时被调用.这个方法不会为最初的渲染调用.
|
||||
|
||||
使用它作为响应 prop 转换的时机(在`render()` 被用 `this.setState()` 更新state调用 之前) .旧的 props 可以通过 `this.props` 访问. 在这个函数里调用 `this.setState()` 不会触发任何额外的渲染.
|
||||
|
||||
```javascript
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
this.setState({
|
||||
likesIncreasing: nextProps.likeCount > this.props.likeCount
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 并没有类似的 `componentWillReceiveState` 方法. 一个即将到来的 prop 转变可能会导致一个 state 变化,但是反之不是. 如果你需要实现一个对 state 变化相应的操作,使用 `componentWillUpdate`.
|
||||
|
||||
|
||||
### Updating: shouldComponentUpdate
|
||||
|
||||
```javascript
|
||||
boolean shouldComponentUpdate(
|
||||
object nextProps, object nextState
|
||||
)
|
||||
```
|
||||
|
||||
当新的props或者state被收到,在渲染前被调用.这个方法不会在最初的渲染或者 `forceUpdate` 时被调用.
|
||||
|
||||
使用此方法作为一个 `return false` 的时机,当你确定新的 props 和 state 的转换不需要组件更新时.
|
||||
|
||||
```javascript
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
return nextProps.id !== this.props.id;
|
||||
}
|
||||
```
|
||||
|
||||
如果 `shouldComponentUpdate` 返回false, `render()` 会在下次state变化前被完全跳过. 另外,`componentWillUpdate` 和 `componentDidUpdate` 将不会被调用.
|
||||
|
||||
默认情况下, `shouldComponentUpdate` 总是返回 `true` 来阻止当 `state` 突变时的细微bug,但是如果你仔细的把 `state` 作为不变量对待并只从 `render()`里的 `props` 和 `state`读,你就可以用一个比较旧的props和state与他们的替换者的实现来重写 `shouldComponentUpdate`.
|
||||
|
||||
如果性能是瓶颈,尤其是随着成百上千的组件,使用 `shouldComponentUpdate` 来加速你的app.
|
||||
|
||||
|
||||
### Updating: componentWillUpdate
|
||||
|
||||
```javascript
|
||||
void componentWillUpdate(
|
||||
object nextProps, object nextState
|
||||
)
|
||||
```
|
||||
|
||||
当新的props或者state被接受时,在渲染前被立即调用.这个方法不会被初始渲染调用.
|
||||
|
||||
使用这个方法作为 在更新发生前执行一些准备 的时机.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> 你 *不能* 在这个方法里使用 `this.setState()` .如果你需要响应一个prop变化来更新state,使用 `componentWillReceiveProps` 来替代.
|
||||
|
||||
|
||||
### Updating: componentDidUpdate
|
||||
|
||||
```javascript
|
||||
void componentDidUpdate(
|
||||
object prevProps, object prevState
|
||||
)
|
||||
```
|
||||
|
||||
在组件的更新被刷新到DOM后立即被调用.这个方法不会被初始渲染调用.
|
||||
|
||||
使用这个方法作为 当组件被更新后在DOM上操作 的时机.
|
||||
|
||||
|
||||
### Unmounting: componentWillUnmount
|
||||
|
||||
```javascript
|
||||
void componentWillUnmount()
|
||||
```
|
||||
|
||||
在组件被从DOM卸载 前 被立即调用.
|
||||
|
||||
在这个方法里执行一些必要的清理操作,比如无效化 timers 或者清理任何被 `componentDidMount` 创建的DOM元素.
|
||||
@@ -59,7 +59,7 @@ controls coords crossOrigin data dateTime defer dir disabled download draggable
|
||||
encType form formAction formEncType formMethod formNoValidate formTarget frameBorder
|
||||
headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode
|
||||
keyParams keyType label lang list loop low manifest marginHeight marginWidth max
|
||||
maxLength media mediaGroup method min minlength multiple muted name noValidate open
|
||||
maxLength media mediaGroup method min minLength multiple muted name noValidate open
|
||||
optimum pattern placeholder poster preload radioGroup readOnly rel required role
|
||||
rows rowSpan sandbox scope scoped scrolling seamless selected shape size sizes
|
||||
span spellCheck src srcDoc srcSet start step style summary tabIndex target title
|
||||
|
||||
@@ -59,7 +59,7 @@ controls coords crossOrigin data dateTime defer dir disabled download draggable
|
||||
encType form formAction formEncType formMethod formNoValidate formTarget frameBorder
|
||||
headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode
|
||||
keyParams keyType label lang list loop low manifest marginHeight marginWidth max
|
||||
maxLength media mediaGroup method min minlength multiple muted name noValidate open
|
||||
maxLength media mediaGroup method min minLength multiple muted name noValidate open
|
||||
optimum pattern placeholder poster preload radioGroup readOnly rel required role
|
||||
rows rowSpan sandbox scope scoped scrolling seamless selected shape size sizes
|
||||
span spellCheck src srcDoc srcSet start step style summary tabIndex target title
|
||||
|
||||
@@ -18,11 +18,11 @@ The following HTML elements are supported:
|
||||
a abbr address area article aside audio b base bdi bdo big blockquote body br
|
||||
button canvas caption cite code col colgroup data datalist dd del details dfn
|
||||
dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
|
||||
h6 head header hr html i iframe img input ins kbd keygen label legend li link
|
||||
main map mark menu menuitem meta meter nav noscript object ol optgroup option
|
||||
output p param picture pre progress q rp rt ruby s samp script section select
|
||||
small source span strong style sub summary sup table tbody td textarea tfoot th
|
||||
thead time title tr track u ul var video wbr
|
||||
h6 head header hgroup hr html i iframe img input ins kbd keygen label legend li
|
||||
link main map mark menu menuitem meta meter nav noscript object ol optgroup
|
||||
option output p param picture pre progress q rp rt ruby s samp script section
|
||||
select small source span strong style sub summary sup table tbody td textarea
|
||||
tfoot th thead time title tr track u ul var video wbr
|
||||
```
|
||||
|
||||
### SVG elements
|
||||
@@ -30,11 +30,11 @@ thead time title tr track u ul var video wbr
|
||||
The following SVG elements are supported:
|
||||
|
||||
```
|
||||
circle clipPath defs ellipse g line linearGradient mask path pattern polygon polyline
|
||||
radialGradient rect stop svg text tspan
|
||||
circle clipPath defs ellipse g image line linearGradient mask path pattern
|
||||
polygon polyline radialGradient rect stop svg text tspan
|
||||
```
|
||||
|
||||
You may also be interested in [react-art](https://github.com/facebook/react-art), a drawing library for React that can render to Canvas, SVG, or VML (for IE8).
|
||||
You may also be interested in [react-art](https://github.com/facebook/react-art), a cross-browser drawing library for React.
|
||||
|
||||
|
||||
## Supported Attributes
|
||||
@@ -53,24 +53,32 @@ These standard attributes are supported:
|
||||
|
||||
```
|
||||
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
|
||||
async autoComplete autoFocus autoPlay capture cellPadding cellSpacing charSet
|
||||
challenge checked classID className cols colSpan content contentEditable contextMenu
|
||||
controls coords crossOrigin data dateTime defer dir disabled download draggable
|
||||
encType form formAction formEncType formMethod formNoValidate formTarget frameBorder
|
||||
headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode
|
||||
keyParams keyType label lang list loop low manifest marginHeight marginWidth max
|
||||
maxLength media mediaGroup method min minlength multiple muted name noValidate open
|
||||
optimum pattern placeholder poster preload radioGroup readOnly rel required role
|
||||
rows rowSpan sandbox scope scoped scrolling seamless selected shape size sizes
|
||||
span spellCheck src srcDoc srcSet start step style summary tabIndex target title
|
||||
type useMap value width wmode wrap
|
||||
async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
|
||||
charSet checked classID className colSpan cols content contentEditable
|
||||
contextMenu controls coords crossOrigin data dateTime default defer dir
|
||||
disabled download draggable encType form formAction formEncType formMethod
|
||||
formNoValidate formTarget frameBorder headers height hidden high href hrefLang
|
||||
htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
|
||||
lang list loop low manifest marginHeight marginWidth max maxLength media
|
||||
mediaGroup method min minLength multiple muted name noValidate nonce open
|
||||
optimum pattern placeholder poster preload radioGroup readOnly rel required
|
||||
reversed role rowSpan rows sandbox scope scoped scrolling seamless selected
|
||||
shape size sizes span spellCheck src srcDoc srcLang srcSet start step style
|
||||
summary tabIndex target title type useMap value width wmode wrap
|
||||
```
|
||||
|
||||
These RDFa attributes are supported (several RDFa attributes overlap with standard HTML attributes and thus are excluded from this list):
|
||||
|
||||
```
|
||||
about datatype inlist prefix property resource typeof vocab
|
||||
```
|
||||
|
||||
In addition, the following non-standard attributes are supported:
|
||||
|
||||
- `autoCapitalize autoCorrect` for Mobile Safari.
|
||||
- `property` for [Open Graph](http://ogp.me/) meta tags.
|
||||
- `color` for `<link rel="mask-icon" />` in Safari.
|
||||
- `itemProp itemScope itemType itemRef itemID` for [HTML5 microdata](http://schema.org/docs/gs.html).
|
||||
- `security` for older versions of Internet Explorer.
|
||||
- `unselectable` for Internet Explorer.
|
||||
- `results autoSave` for WebKit/Blink input fields of type `search`.
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user