React官网的RECENT POSTS浏览

⭐️写在开首

  • 浏览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运用中能够很好的运用ReactJSXPyReact设想的主旨是供应一个转化JSXJavaScript的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 pathfast pathfast 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属性:rxry

  • 同时支撑getInitialStategetDefaultProps

  • 支撑挂载到iframes

  • 表单组件的bugfix

  • 增添react.version

  • 增添react.isValidClass:用户搜检某个值是不是是有效的组件构造函数。

  • 删除React.autoBind。在React v0.4中弃用,如今正式删除。

  • 重命名:React.unmountAndReleaseReactRootNodeReact.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中心运用了。确信背面会有更多的特征到场。

JSXES6方面的支撑我们已在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和通报actiondispatcher

差别的actioins由一个type属性定义。当一切的stores收到action的时刻,它们就运用这个属性来决议怎样相应它。在Flux运用中,storesviews相互自我掌握,它们不会被外部影响。操纵流经由历程stores定义注册的回调进入store, not through setter methods。

使stores自我更新能够防止很多一些MVC运用的复杂状况,比方:各个models之间的团结更新会致使状况的不稳定而且会致使测试异常难题。objectsFlux运用中高度星散,而且严厉准守得墨忒耳定律。如许会致使软件越发可保护、适配、测试以及对新工程师来谁越发轻易明白。

Why We Need a Dispatcher

跟着运用的强大,差别stores之间的依靠必定存在。比方:Store A 必需 Store A 先更新,然后 Store A才晓得怎样去更新本身。这个时刻我们就须要dispatcher能够挪用 Store B的回调,今后再操纵Store A。为了说明这类依靠,Store A 须要通知dispatcher,我须要守候Store B完成后才实行这个actiondispatcher经由历程 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

假如你运用ReactJSX转化器,这个晋级将会异常简朴。

// 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今后将不会再保护JSTransformreact-toolsreact-tools has always been a very thin wrapper around JSTransform.),ReactReact 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

ComponentsElementsComponent instrances三者的差别或许疑惑着很多初学者。为何三个差别的事物协作能够在屏幕上画图。

Managing the Instances

假如你是初学者,你或许最先是和Component classesComponent 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 nodeChild Component关联而且在适宜的时刻建立/烧毁(DOM nodeChild Component)。跟着代码量的增添,组件能够的状况数会按平方级增进,而且父级能够直接接见子组件的实例,未来想要解偶就会变的异常难题。

比起上述,React有什么差别?

Elements Describe the Tree

为处理上述题目,React内里涌现了ElementsAn 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

Elementtype是一个字符串时,它代表着一个具有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 ElementsParent 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

然后Elementstype参数能够使一个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或别的ComponentElements的props中能够包含别的Elements。建立ReactReact Element是低价的,一旦建立了React Element,就不会再发作变化。

一个组件的说明有几个差别的体式格局:classfunctionReact.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能够包含父级衬着时从新实例化了的实例对象的援用,但概念上是相称的(具有雷同的keyvalue)。深比较能够检测到这一点,除过这点又会涌现新的题目,由于没有方法比较两个函数在语义上是不是雷同。

由于言语的限定,偶然我们不能够完成真正意义上相称的语义。在这类状况下,React会挪用componentWillReceiveProps要领(纵然props能够没有转变),使得组件有时机检测新的props,并采用相应的处置惩罚。

如许一来,完成componentWillReceiveProps要领时刻要确保props不能被修正。假如你想在props被转变后实行一些操纵(如收集要求),你的componentWillReceiveProps代码须要搜检props是不是真正的被转变了。

    原文作者:汻烬椮
    原文地址: https://segmentfault.com/a/1190000008967194
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞