⭐️写在开首
浏览React官网的 RECENT POSTS的个人翻译/择要(部份)。
英文片断为官网原文片断。
⭐️为何要运用React
如今已有很多的JavaScript MVC frameworks
降生,然则为何Facebook须要建立React
,而且又是什么缘由致使我们想要去用它?
不是一个
MVC
框架。是一个可用来构建组件化用户界面的库,同时力挺用于构建那些交互数据随时刻转变的可复用的UI组件。不是模板。传统的页面衬着(
JavaScript
衬着),是运用一些模板东西或许直接运用html
标签举行:添补+拼接+衬着。这些构建UI的模板团体笼统了你想要的。
Traditionally, web application UIs are built using templates or HTML directives. These templates dictate the full set of abstractions that you are allowed to use to build your UI.
React以差别的体式格局构建用户界面:分开全部UI为一块一块小的UI组件
UI Components
。这就意味着我们运用一门实在、充溢特征的编程言语来衬着视图,其优于模板衬着有以下几个缘由:javaScript是一门天真、强大的编程言语,其具有构建笼统对象的才。这一点在大型运用中异常主要。
经由历程将标记(标签)与相应的视图逻辑一致起来,React能够越发轻易的举行扩大和保护视图。
经由历程JavaScript code的情势来替换标记(标签)和内容,这个历程没有字符拼接的历程而且削减了XSS破绽。
同时建立了JSX,它是JavaScript的语法扩大。假如比方原生的JavaScript,你更喜好HTML的可读性,就运用它吧!
不能再简朴的相应式数据更新
当你的运用数据跟着时刻变化时,React表现是异常刺眼!
在传统的JavaScript运用中,你须要关注哪些数据变化了而且敕令式的转变DOM的状况,以便坚持视图和数据的一致。以至经由历程指令和数据来供应了一种声明式界面的AngularJS,也是经由历程绑定须要的函数来手动更新DOM节点。
React采纳差别的要领:
当组件初始化时挪用
render
要领,而且天生一个轻量级的视图表达式。这个表达式将会返回一个标签字符串,而且插进去页面文档中去。当数据变化的时刻,
render
要领将被会再次挪用。为了尽量的进步更新效力,我们把先旧数据和新数据传入render
要领举行对照,天生一个最小的变化来操纵DOM。(render
要领返回的值不是字符串也不是一个DOM元素,而是一个轻量级的DOM表达式)。
HTML仅仅只一个最先
由于React有着本身的轻量级的文本表达式,我们能够做一些更酷的事变:
FaceBook运用React替换html绘制canvas动态图。
连系React和Backbone.Rounter能够圆满的构建单页运用(Instagram)。
我们在React内部道理处置惩罚,使得React App既能在web上运转,也能经由历程Objective-C bridge驱动原生IOS视图。
You can run React on the server for SEO, performance, code sharing and overall flexibility。
事宜行动在浏览器中坚持一次,而且相符规范。默许运用事宜代办。
⭐️React v0.3.3
我们将在React v0.4中新增了很多中西,然则与此同时我们宣告了React v0.3.3。这个版本处理了人们在运用中碰到的题目,而且使我们的东西越发轻易运用。
React
许可反复运用同一个DOMNode衬着差别的组件。
React.renderComponent(<div/>, domNode)
React.renderComponent(<span/>, domNode)
⭐️New in React v0.4: Prop Validation and Default Values
我们收到关于React
题目中,有大部份是关于props
的,特别是人们愿望对props
举行考证或许使其有个合理的默许值。
Validation
在运用props之前,我们经常对props的某些参数举行某些特别的处置惩罚,比方:须要肯定这些属性是不是是特定的范例、需求限定某些值、某些参数的身分是必需的。这些考证我们都能够在render内里处置惩罚,然则这回使render显得痴肥!
如今,React v.04
带来的内建的考证模块,你能够写你本身的限定
React.createClass({
propTypes: {
// An optional string prop named "description".
description: React.PropTypes.string,
// A required enum prop named "category".
category: React.PropTypes.oneOf(['News','Photos']).isRequired,
// A prop named "dialog" that requires an instance of Dialog.
dialog: React.PropTypes.instanceOf(Dialog).isRequired
},
...
});
Default Values
在以往的例子内里,我们经常看到以下代码:
React.createClass({
render: function() {
var value = this.props.value || 'default value';
return <div>{value}</div>;
}
});
假如对几个穿插在几个差别组件的props
举行以上操纵,这将会发作大批的冗余代码。在React v0.04
中,你能够以说明的体式格局供应默许值。
React.createClass({
getDefaultProps: function() {
return {
value: 'default value'
};
}
...
});
在render之前,我们运用这些函数举行处置惩罚(我们也会在render
之前支撑一切的考证函数),以保证你在运用的时刻拿到的数据是你所须要的。
Both of these features are entirely optional. We've found them to be increasingly valuable at Facebook as our applications grow and evolve, and we hope others find them useful as well.
⭐️React v0.4.1
React v0.4.1
版本只是举行了小小的修正。主如果举行修复。部份代码在底层修正了,然则这不会影响你挪用我们的大众Api。
React
setState的callback参数,会在组件域挪用。
click事宜已在挪动Safari上支撑。
阻挠已在Object.prototype上存在的事宜毛病处置惩罚。
不必设置先前就已定义了的DOM属性为undefined。
优化对iframe属性的支撑。
增添checksums属性来检测和校验服务端衬着和客户端现实衬着内容的是不是一致。
JSXTransformer
改进环境检测机制,使其能运转在非浏览器环境。
Improved environment detection so it can be run in a non-browser environment.
⭐️Use React and JSX in Python Applications
本日我们很愉快的宣告PyReact
的初始版本的宣告。它使得在你的pyhton
运用中能够很好的运用React
和JSX
。PyReact
设想的主旨是供应一个转化JSX
为JavaScript
的API。
Usage:show me code
from react import jsx
# For multiple paths, use the JSXTransformer class.
transformer = jsx.JSXTransformer()
for jsx_path, js_path in my_paths:
transformer.transform(jsx_path, js_path)
# For a single file, you can use a shortcut method.
jsx.transform('path/to/input/file.jsx', 'path/to/output/file.js')
Django:support the pip
#install
$ pip install PyReact
#use
PIPELINE_COMPILERS = ( 'react.utils.pipeline.JSXCompiler',)
React Page
Jordan Walke 完成了一个完整的react
项目react-page。其支撑客户端和服务端的衬着、运用模板体系举行转化和打包、及时重载。
为何运用服务端衬着?
进步页面初始化速率
在下载
JavaScript
前,一些标签元素将会被展现给用户。在服务端标签元素的构建远远快于客户端。
更快的开辟和构建原型
不必守候任何监听剧本或打包器。
更轻易的布置
SEO
服务端衬着是怎样举行的?
在服务端构建、发送标签给客户端,如许用户能够很快的看到内容。
然后对应的
JavaScript
将会被打包送往客户端。浏览器运转对应
JavaScript
,如许一切的事宜句柄、交互、数据更新等将会无漏洞的对服务端天生的标记举行绑定。肉眼看来这一切彷佛都是发作在客户端,只是更快。
⭐️ React v0.5
Changelog
优化内存运用:经由历程运用
GC PAUSES
(GC:Garbage Collection,渣滓收集,渣滓接纳)机制,削减中心内存分派。提拔机能:为了供应代码运转速率,我们从V8和Nitro中剔除了一些
slow path code
。
在收集装备内里辨别差别的途径是一个很天然的挑选,由于收集装备的首要任务是转发收集包,差别的收集包,在装备内里的处置惩罚途径差别。fast path就是那些能够依据已有状况转发的途径,在这些途径上,网关,二层地点等都已预备好了,不须要缓存数据包,而是能够直接转发。
slow path
是那些须要分外信息的包,比方查找路由,剖析MAC地点等。
first path
是装备收到流上第一个包所走过的途径,比方tcp
内里的syn
包,有些完成把三次握手都放到first path
内里处置惩罚,而有些只需处置惩罚syn
包,其他包就进入fast path
的处置惩罚途径。在NP或许ASIC内里也须要辨别
slow path
和fast path
,fast path
上的包都放在SRAM
内里,而slow path
的包放在DRAM
内里。不过这也非相对。决议处置惩罚途径的是关于速率的斟酌。处置惩罚器的速率,内存的速率等。接见内存的速率由速率和带宽两个要素决议。因而,把SRAM
放到fast path
上,也是很天然的挑选。
fast path: Frontend -> simple code generator -> assembler
slow path: Frontend -> IR optimizer (sometimes more than one level of IR) -> code-generator -> assembler
规范化支撑:
DOM
属性的处置惩罚。在处置惩罚之前不仅有过剩的搜检和开支,而且照样殽杂运用者。如今我们会一向掌握你的属性值为string
直到衬着。支撑
Selection
事宜。支撑夹杂事宜(池化哟)。
支撑一些分外DOM属性:
charSet, content, form, httpEquiv, rowSpan, autoCapitalize
。支撑分外的SVG属性:
rx
、ry
。同时支撑
getInitialState
和getDefaultProps
。支撑挂载到
iframes
。表单组件的
bugfix
。增添
react.version
。增添
react.isValidClass
:用户搜检某个值是不是是有效的组件构造函数。删除
React.autoBind
。在React v0.4中弃用,如今正式删除。重命名:
React.unmountAndReleaseReactRootNode
为React.unmountComponentAtNode
。最先着手于邃密的机能剖析。
更好的支撑服务端衬着。
是React运转于一个严厉的安全策略下成为能够。同时使运用React编写chrome插件成为能够。
JSX
属性
class
改名问className
。增添正告提醒(非临盆环境)。
改良Window兼容性。
⭐️ React v0.9 [RC]
Upgrade Notes
我们JSX
诠释器处置惩罚空格上面举行了转变。简朴来讲就是,在一行上面组件与组件之前的空格将会被保存,而换行(文本节点或许组件)会被疏忽。
<div>
Monkeys:
{listOfMonkeys} {submitButton}
</div>
0.8-
React.DOM.div(null,
" Monkeys: ",
listOfMonkeys, submitButton
)
0.9+
React.DOM.div(null,
"Monkeys:",
listOfMonkeys, " ", submitButton
)
置信这个新特征会异常有空,能够有效削减急忙当中带来的非期待的空格。
假如你愿望保存 背面紧跟换行文本节点 背面的空格,那末你能够在JSX
内里运用这类写法:{"Monkeys: }
。
⭐️ The Road to 1.0 (2014-03-28)
我们在客岁春季宣告了React
,然则我们却故意的没有宣告版本React v1.0
。实在我们已做好了临盆预备,然则我们设计在内部和外部依据开辟者怎样运用React
来生长API和行动特征。在过去的九个月我们学到了很多,而且思索很多关于1.0关于React意味着什么。在过去的两周内,我在多个项目内里概述了我们盘算进入1.0+的天下。本日我誊写一点点给我们的用户,以便用户更好的相识我们的设计。
我们在1.0中主要的目标是说明我们的音讯形式,而且聚焦在一个与我们目标相干的API上面举行处置惩罚。为了完成这个目标,我们消灭一些已碰到的不友好的形式,真正的协助开辟者写出更好的代码。
ES6
在我们正式推出React
之前,我们就思索过怎样在React
内里应用ES6
,即类,以此来进步建立React组件的体验。我们以为运用 React.createClass(…)
不是一个最好的挑选。纵然在运用方面优劣性没有正确的答案,然则我们在向ES6
方面挨近。我们愿望确保这个历程尽量的简朴。比方:
class MyComponent extends React.Component {
render() {
...
}
}
其他一些ES6
的特征我们在React
中心运用了。确信背面会有更多的特征到场。
JSX
在ES6
方面的支撑我们已在react-tools
内里乘船上线。已支撑转化大部份的ES6
代码转换为老浏览器支撑的代码。
Context
只管我们没有在文档中说起过context
,然则它以某种情势在React
确实存在的。
While we haven't documented context, it exists in some form in React already. It exists as a way to pass values through a tree without having to use props at every single point. We've seen this need crop up time and time again, so we want to make this as easy as possible. Its use has performance tradeoffs, and there are known weaknesses in our implementation, so we want to make sure this is a solid feature.
⭐️ React v0.11
getDefaultProps
从React0.11最先,getDefaultProps()
只会在 React.createClass()
挪用的时刻挪用一次,替换本来每次组件衬着时挪用。这就意味着 getDefaultProps()
不会转变他的返回值,同时任何对象将会在一切实例中同享。这个转变提醒了机能,而且使得未来能够更早的在衬着中做 PropTypes check ,这将使我们能够给出更好的毛病提醒。
Rendering to null
自从React宣告以来,开辟者基础都碰到过 render nothing 的状况。通常是返回一个空<div/>
或许<span/>
。有些更智慧的人返回<noscript/>
来防止不要的DOM nodes
。我们对此供应了一个处理方法:return null 。如许能够进一步帮助开辟者写出故意义的代码。在完成上,我们运用了<noscript>
标签举行处置惩罚,只管我们目标是不返回任何东西。由于noscript
并不会影响你的规划,所以你能够放心运用。
// Before
render: function() {
if (!this.state.visible) {
return <span/>;
}
// ...
}
// After
render: function() {
if (!this.state.visible) {
return null;
}
// ...
}
JSX Namespacing
在JSX
内里支撑namespaceing
呼叫招呼我们已听到了很长一段时刻。斟酌到JSX
是JavaScript完成的,所以我们不愿意运用XML namespaceing
。相反,我们运用挑选JavaScript
规范来完成: object property access
。替换为每一个组件分派一个对象,你能够直接如许运用 <Namespace.Component />
。
// Before
var UI = require('UI');
var UILayout = UI.Layout;
var UIButton = UI.Button;
var UILabel = UI.Label;
render: function() {
return <UILayout><UIButton /><UILabel>text</UILabel></UILayout>;
}
// After
var UI = require('UI');
render: function() {
return <UI.Layout><UI.Button /><UI.Label>text</UI.Label></UI.Layout>;
}
Improved keyboard event normalization
依据DOM3,React键盘事宜包含了一个规范化的 e.key
,如许许可你在代码中编写一个简朴的key,而且能够在一切浏览器运转。
handleKeyDown: function(e) {
if (e.key === 'Enter') {
// Handle enter key
} else if (e.key === ' ') {
// Handle spacebar
} else if (e.key === 'ArrowLeft') {
// Handle left arrow
}
}
React
键盘事宜和鼠标事宜也包含了规范化的 e.getModifierState()
。
⭐️ Flux: Actions and the Dispatcher
Flux
是Facebook构建JavaScript
运用的时刻运用的基于单项数据流的运用框架。我们运用Flux
的构建大型运用都是有小的组件构成,Flux
来掌握我们供应的小组件(们)。我们找到了一个异常棒的代码构造构造,我们异常冲动的分享到开源社区。
比方一个完整的框架,Flux
更像一种形式,让你不必增添太多新代码就能够运用Flux
。直到近来的,我们还没有宣告Flux
模块之一: dispatcher
。然则跟着新的Flux code
项目和Flux website
宣告,我们供应我们在临盆项目中运用的dispatcher
。
Where the Dispatcher Fits in the Flux Data Flow
dispatcher
是一个单例。作为数据掌握中心掌握Flux
运用的数据流。简朴的来讲,他就是供应注册回调函数,然后运用肯定的敕令挪用这些回调函数。每一个store
都经由历程dispatcher
注册了回调。当dispatcher
中有新数据来,它运用这些回调关照相应的store
。然后相干顺序经由历程dispatch()
启动回调函数。
Actions and ActionCreators
不管是用户举行界面操纵照样接口返回的新数据进入体系的时刻,这些数据将会被打包送入一个 action
(由内容和action type
构成的对象)。对此,我们经常建立名为ActionCreateors
的辅佐库,用来建立action object
和通报action
给dispatcher
。
差别的actioins
由一个type
属性定义。当一切的stores
收到action
的时刻,它们就运用这个属性来决议怎样相应它。在Flux
运用中,stores
和views
相互自我掌握,它们不会被外部影响。操纵流经由历程stores
定义注册的回调进入store
, not through setter methods。
使stores
自我更新能够防止很多一些MVC
运用的复杂状况,比方:各个models
之间的团结更新会致使状况的不稳定而且会致使测试异常难题。objects
在Flux
运用中高度星散,而且严厉准守得墨忒耳定律。如许会致使软件越发可保护、适配、测试以及对新工程师来谁越发轻易明白。
Why We Need a Dispatcher
跟着运用的强大,差别stores
之间的依靠必定存在。比方:Store A 必需 Store A 先更新,然后 Store A才晓得怎样去更新本身。这个时刻我们就须要dispatcher
能够挪用 Store B的回调,今后再操纵Store A。为了说明这类依靠,Store A 须要通知dispatcher
,我须要守候Store B完成后才实行这个action
。dispatcher
经由历程 waitFor()
供应如许的功用。
dispatch()
要领经由历程回调函数供应了一个简朴的、同步迭代功用:顺次挪用。当waitFor()
在某一个回调中触发,随后住手实行这个回调函数,而且 waitFor()
将供应我们一个有关依靠的新的迭代周期。等这些依靠实行完今后,回调函数再继承实行。
更者,waitFor()
要领但是在同一个store
中不差别的actions
间挪用。
Problems arise, however, if we have circular dependencies. That is, if Store A needs to wait for Store B, and Store B needs to wait for Store A, we could wind up in an endless loop. The dispatcher now available in the Flux repo protects against this by throwing an informative error to alert the developer that this problem has occurred. The developer can then create a third store and resolve the circular dependency.
⭐️Introducing React Elements
If you currently use JSX everywhere, you don't really have to do anything to get these benefits! The updated transformer will do it for you.
If you can't or don't want to use JSX, then please insert some hints for us. Add a React.createFactory call around your imported class when you require it。
New Terminolog
我们为了使新用户更简朴的相识DOM
(和React
的差别之处)。我们运用术语ReactElement
替换<>
,一样ReactNode
替换renderable
。
Creating a ReactElement
我们供应一个API来建立ReactElement
。
var reactElement = React.createElement(type,props,children);
type
参数能够使HTML tag
或许class
。它指导着什么样的HTML tag
或许class
将被衬着和包含哪些props
数据。你也能够只供应一个type
参数建立一个工程函数。
var div = React.createFactory('div');
var reactDivElement = div(props,children);
React Element
的署名就像如许
{
type : string | class,
props : { children, className, etc. },
key : string | boolean | number | null,
ref : string | null
}
Upgrading to 0.12
React With JSX
假如你运用React
的JSX
转化器,这个晋级将会异常简朴。
// If you use node/browserify modules make sure
// that you require React into scope.
var React = require('react');
React
的JSX将会为你建立ReactElement
。
var MyComponent = React.createClass(...);
var MyOtherComponent = React.createClass({
render: function() {
return <MyComponent prop="value" />;
}
});
React Without JSX
在不运用JSX
状况下须要挪用一个组件作为函数,在挪用前你须要明白的建立一个工程函数。
var MyComponentClass = React.createClass(...);
var MyComponent = React.createFactory(MyComponentClass); // New step
var MyOtherComponent = React.createClass({
render: function() {
return MyComponent({ prop: 'value' });
}
});
React
为罕见的HTML elements
内置了工场函数。
var MyDOMComponent = React.createClass({
render: function() {
return React.DOM.div({ className: 'foo' }); // still ok
}
});
The Next Step: ES6 Classes
在v0.12版本后,我们的事情将转向ES6 classes
。我们会坚持向后兼容(React.createclass
)。假如你已在运用ES6转译器,你能够根据下面说明你的组件。
export class MyComponent {
render(){
...
}
};
⭐️Deprecating JSTransform and react-tools
跟着JavaScript
的生长,JSTransform
有点”跟不上时期”,Babel
的涌现能够完整将其替换。v0.14今后将不会再保护JSTransform
和react-tools
(react-tools
has always been a very thin wrapper around JSTransform.),React
和React Native
如今都运用三方的Babel
的JSX编译器处置惩罚.
Other Deprecations
esprima-fb
ECMAScript剖析器
JSXTransformer
JSXTransformer is another tool we built specifically for consuming JSX in the browser. It was always intended as a quick way to prototype code before setting up a build process. It would look for <script> tags with type=”text/jsx” and then transform and run. This ran the same code that react-tools ran on the server.
⭐️ReactDOM.render and the Top Level React API
在React
的天下内里一切都是组件,然则你触及的代码、工程并非都是由React
来构建的。所以,须要你编写管道代码举行二者的链接。处置惩罚这些事变的主要API为:
ReactDOM.render(reactElment,domContainerNode)
这须要你供应一个分外的DOM容器。
当把React
插进去在单页运用中时刻,须要你手动的掌握生命周期。React
不会自动开释元素,须要手动掌握:
ReactDOM.unmountComponentAtNode(domComtainerNode)
It is not unique to the DOM. If you want to insert a React Native view in the middle of an existing iOS app you will hit similar issues.
Object Oriented Updates
假如你挪用ReactDOM.render
屡次,那末对应组件上次的props将会被最新的完整替换。
ReactDOM.render(<App locale="en-US" userID={1} />, container);
// props.userID == 1
// props.locale == "en-US"
ReactDOM.render(<App userID={2} />, container);
// props.userID == 2
// props.locale == undefined ??!?
在面向对象编程中,一切的状况依靠实例存在,经由历程掌握状况的转变掌握运用变化。假如你在一个运用面向对象API的app内里运用React
,你或许会惊奇或许渺茫当你设置一个属性的时刻会致使其他属性的消逝。
对此我们供应了一个辅佐函数setProps
来许可你一次只更新所希冀的属性。
Unfortunately this API lived on a component instance, required React to keep this state internally and wasn’t very natural anyway. Therefore, we’re deprecating it and suggest that you build it into your own wrapper instead.
class ReactComponentRenderer {
constructor(klass, container) {
this.klass = klass;
this.container = container;
this.props = {};
this.component = null;
}
replaceProps(props, callback) {
this.props = {};
this.setProps(props, callback);
}
setProps(partialProps, callback) {
if (this.klass == null) {
console.warn(
'setProps(...): Can only update a mounted or ' +
'mounting component. This usually means you called setProps() on ' +
'an unmounted component. This is a no-op.'
);
return;
}
Object.assign(this.props, partialProps);
var element = React.createElement(this.klass, this.props);
this.component = ReactDOM.render(element, this.container, callback);
}
unmount() {
ReactDOM.unmountComponentAtNode(this.container);
this.klass = null;
}
}
Object-oriented APIs don’t look like that though. They use setters and methods. I think we can do better. If you know more about the component API that you’re rendering, you can create a more natural object-oriented API around your React component.
class ReactVideoPlayer {
constructor(url, container) {
this._container = container;
this._url = url;
this._isPlaying = false;
this._render();
}
_render() {
ReactDOM.render(
<VideoPlayer url={this._url} playing={this._isPlaying} />,
this._container
);
}
get url() {
return this._url;
}
set url(value) {
this._url = value;
this._render();
}
play() {
this._isPlaying = true;
this._render();
}
pause() {
this._isPlaying = false;
this._render();
}
destroy() {
ReactDOM.unmountComponentAtNode(this._container);
}
}
⭐️React Components, Elements, and Instances
Components
、Elements
、Component instrances
三者的差别或许疑惑着很多初学者。为何三个差别的事物协作能够在屏幕上画图。
Managing the Instances
假如你是初学者,你或许最先是和Component classes
和Component classes Instances
打交道。栗如,建立class
来讲明Button
组件。当运用运转时,你能够有Button
组件的多个实例,每一个实例有着本身的属性和当地状况。这是传统的面向对象的UI编程。
在传统的UI模块中,由你来掌握建立和烧毁组件实例。栗:假如一个Form
组件要衬着一个Button
组件。它须要一个Button
的实例而且手动坚持和任何信息的交换。
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);
}
}
}
上面的伪复合UI代码(或许增添更多)都是根据面向对象的体式格局运用库,就像Backbone
一样。每一个组件实例都坚持DOM node
、Child Component
关联而且在适宜的时刻建立/烧毁(DOM node
、Child Component
)。跟着代码量的增添,组件能够的状况数会按平方级增进,而且父级能够直接接见子组件的实例,未来想要解偶就会变的异常难题。
比起上述,React
有什么差别?
Elements Describe the Tree
为处理上述题目,React
内里涌现了Elements
。An element is a plain object describing a component instance or DOM node and its desired properties.
它包含了一些唯一的信息:组件范例(Button
)、属性(color
)和具有的Child Elements
。
PlainObject:JSON情势定义的一般对象或许new Object()建立的简朴对象。
一个Element
不是一个现实的实例。相反,他是一种通知React
什么须要衬着在屏幕上的体式格局。你不能挪用任安在Elements
上面的要领,它仅仅是一个具有两个字段属性的不可变对象(type : ( string | ReactClass )
和props : Object
)。
DOM Elements
当Element
的type
是一个字符串时,它代表着一个具有props
作为属性的DOM node
(这些就是React
将会衬着的)。栗子:
{
type: 'button',
props: {
className: 'button button-blue',
children: {
type: 'b',
props: {
children: 'OK!'
}
}
}
}
⇩
<button class='button button-blue'>
<b>
OK!
</b>
</button>
关于Elements
嵌套的题目,根据通例,我们愿望建立一个Elements
树,然后指定一个或很多个Child Elements
作为其容器/父元素的children props
。
最主要的一点照样Child Elements
和Parent Elements
仅仅只一中形貌体式格局并非实在实例。当你建立它们的时刻并不触及在屏幕上面显现的东西。建立和抛弃他们都是可有可无的。
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
然后Elements
的type
参数能够使一个React Component
对应的函数或许类。
{
type : Button,
props : {
color : "blue",
children : "OK!",
}
}
这是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.
这个特机能够让你建立一个DangerButton
,它是一个具有特定color
属性值的Button
组件。而且不必小心Button
是不是衬着为DOM <button>
、<div>
或许其他的。
const DangerButton = ({ children }) => ({
type: Button,
props: {
color: 'red',
children: children
}
});
你能够夹杂搭配DOM/Component Elements
在一个简朴的Element Tree
内里。
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'
}
}]
});
或许你运用JSX
const DeleteAccount = () => (
<div>
<p>Are you sure?</p>
<DangerButton>Yep</DangerButton>
<Button color='blue'>Cancel</Button>
</div>
);
这类夹杂和婚配有助于下降组件之间的耦合度,因而它们完整能够经由历程一下的构造同时表达is-a和has-a的关联
Button组件是一个具有特定属性的DOM元素button;
DangerButton组件是一个具有特定属性的Button组件;
DeleteAccount在一个div元素中包含一个Button组件和一个DangerButton组件。
Components Encapsulate Element Trees
当React
收到一个运用函数或许类作为type
值得Element
的时刻,它晓得讯问对应的组件什么样的Element
须要被衬着,并赋予相应的props
。
当看到这个Element
的时刻
{
type: Button,
props: {
color: 'blue',
children: 'OK!'
}
}
React
将会讯问Button Component
什么须要衬着。Button Component
将会返回
{
type: 'button',
props: {
className: 'button button-blue',
children: {
type: 'b',
props: {
children: 'OK!'
}
}
}
}
React
将反复此历程,直到它晓得页面上的每一个组件有效的底层DOM
标签元素。
前面提到的Form
实例运用React
能够如许
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'
}
};
};
以上,关于React Component
组件,props
是输入,Element Tree
是输出。
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.
返回的元素树包含形貌DOM node
及形貌别的Component
。这能够让我们独登时编写UI部份,而无需依靠它们的内部DOM
构造。
我们使React
建立、更新、烧毁实例。
我们运用Components
返回的Elements
形貌实例,React
担任治理实例。
Components Can Be Classes or Functions
// 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.
Top-Down Reconciliation
ReactDOM.render({
type: Form,
props: {
isSubmitted: false,
buttonText: 'OK!'
}
}, document.getElementById('root'));
你当运转上述代码的时刻,React
会讯问Form
组件返回的Element Tree
,赋予对应props
。
// 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 which starts when you call ReactDOM.render() or 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).
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.
Summary
Element
只是是PlainObject
,用来形貌呈如今屏幕上的DOM node
或别的Component
。Elements
的props中能够包含别的Elements
。建立ReactReact Element
是低价的,一旦建立了React Element
,就不会再发作变化。
一个组件的说明有几个差别的体式格局:class
、function
、React.creatClass
。不管哪一种体式格局,老是props
为输入,Element Tree
为输出。
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.(实例就是对组件类中this的援用。)
末了,建立React Elements
运用React.createElement()
、JSX
或许Element Factory helper
。别在现实代码中编写PlainObect
情势的Elements
(只须要晓得在底层他们是PlainObject
就好了)。
⭐️(A => B) !=> (B => A)
文档内里关于componentWillReceiveProps
的陈说为:componentWillReceiveProps
在对应props
被转变的时刻挪用,并作为rerender
的效果。这致使部份用户以为:componentWillReceiveProps
被挪用了对应props
肯定会变化。逻辑上这个结论是不正确的。
formal logic/mathematics
:A包含着B,不代表B包含着A。有很多缘由致使componentWillReceiveProps
被挪用,纵然对应的props
没有转变。
你假如不置信,能够尝尝运用正确的props
三次挪用ReactDOM.render()
,而且监控componentWillReceiveProps
的挪用。
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);
以上代码componentWillReceiveProps
会被挪用两次。
为了明白为何会如许,我们须要想一想会发作什么。在初始衬着和两次后续更新之间数据能够已被转变了,假如代码像下面如许实行:
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并没有方法晓得。因而,React
须要挪用componentWillReceiveProps
要领,由于组件须要新props
来关照(纵然新的props
和旧props
完整雷同)。
你能够会以为,React
能够运用很奇妙的检测机制来检测是不是相称,但这类主意也有一些题目
旧的myData和新的myData现实上是雷同的物理对象(仅对象内部的值被转变)。由于采纳的是
triple-equals-equal
,搜检是不是雷同的时刻并不会通知我们值是不是被转变。唯一能够的处理要领就是建立数据的一个深拷贝副本,接着做深比较,但这对照较大的数据构造而言过于高贵(特别是轮回)myData对象能够包含对函数的援用,该函数经由历程闭包猎取变量。
React
没有方法猎取闭包内部的变量值,因而也没有方法复制和考证它们是不是相称myData能够包含父级衬着时从新实例化了的实例对象的援用,但概念上是相称的(具有雷同的
key
和value
)。深比较能够检测到这一点,除过这点又会涌现新的题目,由于没有方法比较两个函数在语义上是不是雷同。
由于言语的限定,偶然我们不能够完成真正意义上相称的语义。在这类状况下,React
会挪用componentWillReceiveProps
要领(纵然props
能够没有转变),使得组件有时机检测新的props,并采用相应的处置惩罚。
如许一来,完成componentWillReceiveProps
要领时刻要确保props
不能被修正。假如你想在props
被转变后实行一些操纵(如收集要求),你的componentWillReceiveProps
代码须要搜检props
是不是真正的被转变了。