跟着官网的例子学Reacjs (一)FilterableProductTable
最近开始学习React,发现最好的方法不是看这个书那个书,而是直接上官网,一步步的跟着学习,真的获益匪浅。许多翻译的书上漏掉的知识点都可以学到。
入门的一些准备工作可以参照官网的步骤,引入依赖的核心包,就不多说了,直接上官网的第二个具体例子,一个过滤产品列表的Table:https://facebook.github.io/react/docs/thinking-in-react.html
这篇文章主要介绍的并不是API的一些使用,而是向刚入门的同学介绍使用React设计组件时的一些思路,思考怎么样来更好的使用React。
1. 首先,要做的是这么个东西

一个很简单的table列表,带了一个搜索功能,只是界面比较简陋。。。(作者自己也调侃说这肯定是个糟糕的设计,哈哈)。鉴于此,使用bootstrap稍微规整了一下
2. 接着,作者分析了这个组件该怎么划分:要本着最小原则,实现单一功能得原则,划分了五个组件

每种颜色代表一个组件,最后组件的关系如下,很好理解:
FilterableProductTable
SearchBarProductTableProductCategoryRowProductRow
下面直接进入主题,来code这五个组件
2.1 先来个最简单的,SearchBar
这个组件和其他的组件相对独立,而且就一个input框和一个复选框
var SearchBar = React.createClass({
render: function () {
return (
<form>
<input type="text" placeholder="input product name"/><br/>
<input id="FPT_SearchBar_in_stock" type="checkbox"/>
<label htmlFor="FPT_SearchBar_in_stock">only show product in stock</label>
</form>
);
}
});
render方法只渲染了一个form,里面一个俩input,搞定
2.2 ProductCategoryRow
产品分类组件,也相对简单些,只需要接受父组件的一个分类的名称就可以了
var ProductCategoryRow = React.createClass({
render:function(){
return (
<tr>
<th colSpan="2">{this.props.category}</th>
</tr>
);
}
});
2.3 ProductRow
产品明细组件,接受父类的产品信息,并且判断,如果没有库存了,产品名字要显示为红色
var ProductRow = React.createClass({
render:function(){
//如果没有库存,名字显示为红色
var name = this.props.product.stocked
? this.props.product.name
: <span style={{color:'red'}}>{this.props.product.name}</span>;
return(
<tr>
<td>{name}</td>
<td>{this.props.product.price}</td>
</tr>
);
}
});
2.4 ProductTable
产品列表组件负责渲染所有的产品信息,通过接收父类穿进来的products属性,遍历循环,并负责给两个子控件ProductCategoryRow 和 ProductRow 赋值
var ProductTable = React.createClass({
//根据数据获得需要render的rows
formatProducts: function () {
var result = [];
var category = "";
this.props.products.forEach((product)=> {
if(category !== product.category){
result.push(<ProductCategoryRow category={product.category} key={product.category}/>);
}
result.push(<ProductRow product={product} key={product.name}/>);
category = product.category;
});
return result;
},
render: function () {
var products = this.formatProducts();
return (
<table className="table table-bordered">
<thead>
<tr>
<th>
Name
</th>
<th>
Price
</th>
</tr>
</thead>
<tbody>
{products}
</tbody>
</table>
);
}
});
2.5 最后一个组件FilterableProductTable
这个组件只负责给ProductTable的products属性赋值就可以了,然后把SearchBar组件也包含进来。
var FilterableProductTable = React.createClass({
render: function () {
return (
<div>
<SearchBar />
<ProductTable products={this.state.data}/>
</div>
);
},
getInitialState: function () {
return {
data: [],
filterName: '',
onlyStock: ''
};
},
//组件显示后(生命周期中的方法)
componentDidMount: function () {
var defaultData = [
{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"}
];
setTimeout(function () {
this.setState({data: defaultData});
}.bind(this), 2000);
},
addOneProduct: function () {
var oldData = this.state.data;
var newData = {category: "Electronics", price: "$123", stocked: true, name: (new Date) - 0};
oldData.push(newData);
this.setState({data: oldData});
}
});
这里做了一些处理,就是每个组件都有一个生命周期,其中内置的函数componentDidMount函数负责在组件显示后调用,延迟2s给data传递了本地数据,这样就有一个过了两秒数据才加载出来的感觉
通过上面的两步,页面一个纯静态的样子就出来了,过滤的功能还没有加。

然后作者提到了一个关键的概念,就是React中的props和state,他俩的区别在哪?什么时候使用state?
作者给出了一个解决的方法:
让我们通过每一个问题,找出哪一个是state。简单地询问每一块数据三个问题: 它是从通过父组件的props传递?如果是这样,它可能不是state。
是否随着时间的推移保持不变?如果是这样,它可能不是state。
你可以基于组件中的任何其他state或props计算它?如果是这样,它不是state。
大概的翻译了一下原文,如上。这应该就是使用state的一个原则吧。
接下来,开始实现过滤的功能之前,根据上面的原则,我们思考我们要实现的这几个组件中,到底有哪些地方要用到state?
没错,一共3个:
1、整个表格的数据来源,正常情况下是从服务器请求的,所以使用state
2、SearchBar中的搜索框的输入值,因为是用户输入的,时刻在发生变化
3、SearchBar中的复选框
3、按照上面整理的,需要修改之前的两个组件
var FilterableProductTable = React.createClass({
render: function () {
return (
<div>
<SearchBar filterName={this.state.filterName} onlyStock={this.state.onlyStock} onSearchChange={this.handleSearchChange}/>
<ProductTable products={this.state.data} filterName={this.state.filterName} onlyStock={this.state.onlyStock}/>
</div>
);
},
getInitialState: function () {
return {
data: [],
filterName: '',
onlyStock: false
};
},
//组件显示后(生命周期中的方法)
componentDidMount: function () {
var defaultData = [
{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"}
];
setTimeout(function () {
this.setState({data: defaultData});
}.bind(this), 2000);
},
//当搜索框变化时的处理函数
handleSearchChange:function(filterName, onlyStock){
this.setState({
filterName: filterName,
onlyStock: onlyStock
});
},
addOneProduct: function () {
var oldData = this.state.data;
var newData = {category: "Electronics", price: "$123", stocked: true, name: (new Date) - 0};
oldData.push(newData);
this.setState({data: oldData});
}
});
var SearchBar = React.createClass({
render: function () {
return (
<form>
<input type="text" placeholder="input product name"
ref="filterTextInput"
value={this.props.filterName}
onChange={this.handleChange} /><br/>
<input id="FPT_SearchBar_in_stock" type="checkbox"
ref="inputOnlyStock"
checked={this.props.onlyStock}
onChange={this.handleChange} />
<label htmlFor="FPT_SearchBar_in_stock">only show product in stock</label>
</form>
);
},
handleChange:function(){
this.props.onSearchChange(this.refs.filterTextInput.value, this.refs.inputOnlyStock.checked);
}
});
OK,完成。
完整代码可以到我的github上下载运行:https://github.com/lyc-chengzi/reactProject
后续新的例子会继续往上整合,并且用webpack来打包,希望大家一起学习
跟着官网的例子学Reacjs (一)FilterableProductTable的更多相关文章
- angular2使用官网npm install下载依赖失败的处理方法
上一两个月在学习angular2,在下载依赖阶段看官网是直接自动下载的,[npm install] 就能把依赖全部弄下来.不过作为新手的我,是倒腾来倒腾去都倒不出来,因为老是报同一个错.官网也还有手动 ...
- 官网英文版学习——RabbitMQ学习笔记(一)认识RabbitMQ
鉴于目前中文的RabbitMQ教程很缺,本博主虽然买了一本rabbitMQ的书,遗憾的是该书的代码用的不是java语言,看起来也有些不爽,且网友们不同人学习所写不同,本博主看的有些地方不太理想,为此本 ...
- 跟着minium官网介绍学习minium-----(一)
某天,再打开微信开发者工具的时候收到一条推送.说是微信小程序自动化框架 Python 版 -- Minium 公测. Url如下: https://developers.weixin.qq.com/c ...
- 超详细教程2021新版oracle官网下载Windows JAVA-jdk11并安装配置(其他版本流程相同)
异想之旅:本人博客完全手敲,绝对非搬运,全网不可能有重复:本人无团队,仅为技术爱好者进行分享,所有内容不牵扯广告.本人所有文章发布平台为CSDN.博客园.简书和开源中国,后期可能会有个人博客,除此之外 ...
- vivo官网APP全机型UI适配方案
vivo 互联网客户端团队- Xu Jie 日益新增的机型,给开发人员带来了很多的适配工作.代码能不能统一.apk能不能统一.物料如何选取.样式怎么展示等等都是困扰开发人员的问题,本方案就是介绍不同机 ...
- RavenDB官网文档翻译系列第一
本系列文章主要翻译自RavenDB官方文档,有些地方做了删减,有些内容整合在一起.欢迎有需要的朋友阅读.毕竟还是中文读起来更亲切吗.下面进入正题. 起航 获取RavenDB RavenDB可以通过Nu ...
- maven向本地仓库导入jar包(处理官网没有的jar包)
对于官网没有的jar包,maven向本地仓库导入jar包用如下命令 mvn install:install-file -DgroupId=包名 -DartifactId=项目名 -Dversion=版 ...
- PHP环境配置-从Apache官网下载windows版apache服务器
由于个人有强迫倾向,下载软件都喜欢从官网下载,摸索了好久终于摸清楚怎么从Apache官网下载windows安装版的Apache服务器了,现在分享给大家. 进入apache服务器官网http://htt ...
- tornado web高级开发项目之抽屉官网的页面登陆验证、form验证、点赞、评论、文章分页处理、发送邮箱验证码、登陆验证码、注册、发布文章、上传图片
本博文将一步步带领你实现抽屉官网的各种功能:包括登陆.注册.发送邮箱验证码.登陆验证码.页面登陆验证.发布文章.上传图片.form验证.点赞.评论.文章分页处理以及基于tornado的后端和ajax的 ...
随机推荐
- SqlServer2012 数据库的同步之发布+订阅
文章参考了百度过的文章,因为版本不同,操作中也遇到了很多问题,现在整理一下,希望对各位朋友有所帮助. 发布订阅份为两个步骤:1.发布.2订阅.首先在数据源数据库服务器上对需要同步的数据进行发布,然后在 ...
- [Asp.net 开发系列之SignalR篇]专题一:Asp.net SignalR快速入门
一.前言 之前半年时间感觉自己有点浮躁,导致停顿了半年多的时间没有更新博客,今天重新开始记录博文,希望自己可以找回初心,继续沉淀.由于最近做的项目中用到SignalR技术,所以打算总结下Asp.net ...
- 基于ABP的应用执行Update-Database出现异常的解决办法
今天在QQ群中看到有网友在更新数据库执行Update-Database时出现下面的错误: 为了能让搜索引擎搜索到,特意加上该错误的文字说明: 在与 SQL Server 建立连接时出现与网络相关的或特 ...
- memcache(三)内存管理
memcached(三)内存管理 memcached使用预申请的方式来管理内存的分配,从而避免内存碎片化的问题.如果采用mallo和free来动态的申请和销毁内存,必然会产生大量的内存碎片. 基本知识 ...
- multiOTP配置安装
https://code.google.com/p/google-authenticator/ 是google提供的OTP解决方案. http://www.multiotp.net/ 是一个开源otp ...
- UIViewController的生命周期
生命周期 我们建立一个简单的模型来测试生命周期:新建两个ViewController,一个是主视图控制器(main ViewController,以下简称mainVC),一个是副视图控制器(sub V ...
- 说说设计模式~装饰器模式(Decorator)
返回目录 装饰器模式,也叫又叫装饰者模式,顾名思义,将一个对象进行包裹,包装,让它变成一个比较满意的对象,这种模式在我们平时项目开发中,经常会用到,事实上,它是处理问题的一种技巧,也很好的扩展了程序, ...
- MVVM架构~knockoutjs系列之从Knockout.Validation.js源码中学习它的用法
返回目录 说在前 有时,我们在使用一个插件时,在网上即找不到它的相关API,这时,我们会很抓狂的,与其抓狂,还不如踏下心来,分析一下它的源码,事实上,对于JS这种开发语言来说,它开发的插件的使用方法都 ...
- 360路由器刷openwrt、不死uboot、双系统 、wifi中继
该类教程网上有很多,但是很多不全,给小白用户造成了很多困扰.我也是按照网上的教程刷了半天,才熟悉了是怎么个回事.这里整理成教程. 注意: 请看教程步骤走,不要跳跃性刷机.不懂的术语.软件,若本文无介绍 ...
- JS的脚本语言
js的脚本语言全程javascript在网页里面使用的脚本语言:分类:1.嵌入网页里面2.在外部脚本标签可以写在网页的任何地方,但一般都写在网页的底部:<script type="te ...