React.js编程思想

React.js编程思想
React.js编程思想

React.js编程思想

张小俊128发布在使用React.js开发web应用view:7459

在文章任何区域双击击即可给文章添加【评注】!浮到评注点上可以查看详情。

隐藏标注

React.js编程思想

JavaScript框架层出不穷,在很多程序员看来,React.js是创建大型、快速的Web应用的最好方式。这一款由Facebook出品的JS框架,无论是在Facebook还是在Instagram中,它的表现都非常出色。

使用React.js的好处多多,但是其中非常好的一部分是它能够让你重新思考如何创建一个web应用。在本文中,我们将通过一步一步的创建一个产品数据表,并以此过程带领你思考和领悟React.js的编程思想。

步骤零:创建一些伪数据

假设现在我们已经有了一个JSON API和一些伪数据。如下图所示。当然,现在的设计看起来非常糟糕,但是它可以体现出我们将要创建的应用结构:

同时,我们可以通过JSON API返回下列数据:

[

{category:"Sporting Goods", price:"$49.99", stocked:true, name:"Football"}, {category:"Sporting Goods", price:"$9.99", stocked:true, name:"Baseball"}, {category:"Sporting Goods", price:"$29.99", stocked:false, name:"Basketball"}, {category:"Electronics", price:"$99.99", stocked:true, name:"iPod Touch"}, {category:"Electronics", price:"$399.99", stocked:false, name:"iPhone 5"}, {category:"Electronics", price:"$199.99", stocked:true, name:"Nexus 7"}

];

第一步–将你的UI打散为层级组件

你需要做的第一件事情是在每一个组件(以及子组件)周围画上一个框,然后给每个组件起一个名字。如果设计图是由一个设计师给你的,他通常已经帮你完成了这件事情,因此你可以跑去问他设计图中各个层的名字,并以这些名字为你的React组件命名。

但是我们怎么知道哪些部分应该是一个组件呢?想象一下,加入你现在不是在创建一个应用,而是在创建一个新的函数或者对象,你会怎么做。在这里,我们最好遵循”单一任务原则”,也就是说,一个组件最好只是做一件事情。如果一个组件的任务有所增加,那么你应该考虑是不是要把这个组件拆成几个更小的组件。

由于你经常需要讲一个JSON数据模型展示给用户,因此你需要检查这个模型结构是否正确以便你的UI(在这里指的就是你的组件结构)是否能够正确的映射到这个模型上。这是因为用户界面和数据模型在信息构造方面都要一直,这意味着将你可以省下很多将UI分割成组件的麻烦事。你需要做的仅仅只是将数据模型分隔成一小块一小块的组件以便它们都能够表示成组件。

在上面的示意图中,你可以看到在我们这个简单的应用中,包含着5个组件:

1.FilterableProductTable(橙色): 包含着整个例子

2.SearchBar(蓝色): 接收用户的输入

3.ProductTable(绿色): 基于用户输入展示和过滤数据集合

4.ProductCategoryRow(青色): 为每一种类型展示一个头部数据

5.ProductRow(红色): 为每种产品展示一行

{https://www.360docs.net/doc/84308717.html,}

;

return(

{name}

{this.props.product.price}

);

}

});

var ProductTable = React.createClass({

render:function(){

var rows =[];

var lastCategory =null;

this.props.products.forEach(function(product){

if(product.category !== lastCategory){

rows.push();

}

rows.push();

lastCategory = product.category;

});

return(

{rows}

NamePrice

);

}

});

var SearchBar = React.createClass({

render:function(){

return(

Only show products in stock

);

}

});

var FilterableProductTable = React.createClass({ render:function(){

return(

);

}

});

var PRODUCTS =[

为了能够正确的创建应用,首先要思考的第一件事情是应用状态的集合。标准很简单:不要重复你自己。例如如果你创建了一个TODO列表,你只需要创建一个TODO项目列表,而不需要专门分出一个状态参数来记录TODO项目的数量。当你想要渲染这个TODO数量时,你只需要直接获取TODO数组的长度即可。

现在思考一下例子中的数据。我们拥有:

?原始的产品列表

?用户输入的搜索关键字

?复选框的值

?过滤之后的产品列表

现在我们来看看上面这些数据,看看哪一个是state。问自己三个问题:

1.这个数据是否来自父组件中的props?如果是,那么它不是state。

2.它会随时间改变吗?如果不是,那么它不是state。

3.它能够基于组件中的任何state或者props计算出来吗?如果是,那么它不是state。

原始的产品列表作为props传递到组件中,因此它不是state。搜索字段和复选框因为会随时间变化并且不能够由其他state或者props计算出,因此是state。最后,产品的过滤列表不是state,因为它可以根据原始数据、搜索字段以及复选框一起计算出。

因此,我们的state包括:

?用户输入的搜索字段

?复选框的值

步骤四:弄清楚state应该存在于什么地方

/** @jsx React.DOM */

var ProductCategoryRow = React.createClass({

render:function(){

return({this.props.category});

}

});

var ProductRow = React.createClass({

render:function(){

var name = this.props.product.stocked ?

https://www.360docs.net/doc/84308717.html, :

{https://www.360docs.net/doc/84308717.html,}

;

return(

{name}

{this.props.product.price}

);

}

});

var ProductTable = React.createClass({

render:function(){

var rows =[];

var lastCategory =null;

this.props.products.forEach(function(product){

if(https://www.360docs.net/doc/84308717.html,.indexOf(this.props.filterText)===-1||(!product.stocked && this.props.inStoc kOnly)){

return;

}

if(product.category !== lastCategory){

rows.push();

}

rows.push();

lastCategory = product.category;

}.bind(this));

return(

{rows}

NamePrice

);

}

});

var SearchBar = React.createClass({

render:function(){

return(

Only show products in stock

);

}

});

var FilterableProductTable = React.createClass({

getInitialState:function(){

return{

filterText:'',

inStockOnly:false

};

},

render:function(){

return(

filterText={this.state.filterText}

inStockOnly={this.state.inStockOnly}

/>

products={this.props.products}

filterText={this.state.filterText}

inStockOnly={this.state.inStockOnly}

/>

);

}

});

var PRODUCTS =[

{category:'Sporting Goods', price:'$49.99', stocked:true, name:'Football'},

{category:'Sporting Goods', price:'$9.99', stocked:true, name:'Baseball'},

{category:'Sporting Goods', price:'$29.99', stocked:false, name:'Basketball'},

{category:'Electronics', price:'$99.99', stocked:true, name:'iPod Touch'},

{category:'Electronics', price:'$399.99', stocked:false, name:'iPhone 5'},

{category:'Electronics', price:'$199.99', stocked:true, name:'Nexus 7'}

];

React.renderComponent(, document.body);

现在我们已经弄清楚了state集合。下面我们要做的事情就是弄清楚这些state应该存在什么地方。

记住:React的数据是通过层级组件单向流动。弄清楚哪个组件应该拥有state并不是一件容易的事情。这往往是React新手最容易弄错的地方。

首先,对于应用中的每一个state,你需要:

?找出那些需要基于state渲染的组件

?找出一个公共的组件(也就是能够包含所有可能涉及state的组件的组件)

?公共组件以及之外的组件应该拥有这个state

?如果你找不出一个拥有state的组件,创建一个简单的可以包含这个state的组件,然后将它添加到公共组件之上

具体到例子中的应用:

{https://www.360docs.net/doc/84308717.html,}

;

return(

{name}

{this.props.product.price}

);

}

});

var ProductTable = React.createClass({

render:function(){

console.log(this.props);

var rows =[];

var lastCategory =null;

this.props.products.forEach(function(product){

if(https://www.360docs.net/doc/84308717.html,.indexOf(this.props.filterText)===-1||(!product.stocked && this.props.inStoc kOnly)){

return;

}

if(product.category !== lastCategory){

rows.push();

}

rows.push();

lastCategory = product.category;

}.bind(this));

return(

{rows}

NamePrice

);

}

});

var SearchBar = React.createClass({

handleChange:function(){

this.props.onUserInput(

this.refs.filterTextInput.getDOMNode().value,

this.refs.inStockOnlyInput.getDOMNode().checked );

},

render:function(){

return(

type="text"

placeholder="Search..."

value={this.props.filterText}

ref="filterTextInput"

onChange={this.handleChange}

/>

type="checkbox"

value={this.props.inStockOnly}

ref="inStockOnlyInput"

onChange={this.handleChange}

/>

Only show products in stock

);

}

});

var FilterableProductTable = React.createClass({

getInitialState:function(){

return{

filterText:'',

inStockOnly:false

};

},

handleUserInput:function(filterText, inStockOnly){ this.setState({

filterText: filterText,

inStockOnly: inStockOnly

});

},

render:function(){

return(

filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} onUserInput={this.handleUserInput} />

相关主题