跟着官网的例子学Reacjs (一)FilterableProductTable
2016-07-15 16:32
681 查看
最近开始学习React,发现最好的方法不是看这个书那个书,而是直接上官网,一步步的跟着学习,真的获益匪浅。许多翻译的书上漏掉的知识点都可以学到。
入门的一些准备工作可以参照官网的步骤,引入依赖的核心包,就不多说了,直接上官网的第二个具体例子,一个过滤产品列表的Table:https://facebook.github.io/react/docs/thinking-in-react.html
这篇文章主要介绍的并不是API的一些使用,而是向刚入门的同学介绍使用React设计组件时的一些思路,思考怎么样来更好的使用React。
1. 首先,要做的是这么个东西
一个很简单的table列表,带了一个搜索功能,只是界面比较简陋。。。(作者自己也调侃说这肯定是个糟糕的设计,哈哈)。鉴于此,使用bootstrap稍微规整了一下
2. 接着,作者分析了这个组件该怎么划分:要本着最小原则,实现单一功能得原则,划分了五个组件
每种颜色代表一个组件,最后组件的关系如下,很好理解:
下面直接进入主题,来code这五个组件
2.1 先来个最简单的,SearchBar
这个组件和其他的组件相对独立,而且就一个input框和一个复选框
render方法只渲染了一个form,里面一个俩input,搞定
2.2 ProductCategoryRow
产品分类组件,也相对简单些,只需要接受父组件的一个分类的名称就可以了
2.3 ProductRow
产品明细组件,接受父类的产品信息,并且判断,如果没有库存了,产品名字要显示为红色
2.4 ProductTable
产品列表组件负责渲染所有的产品信息,通过接收父类穿进来的products属性,遍历循环,并负责给两个子控件ProductCategoryRow 和 ProductRow 赋值
2.5 最后一个组件FilterableProductTable
这个组件只负责给ProductTable的products属性赋值就可以了,然后把SearchBar组件也包含进来。
这里做了一些处理,就是每个组件都有一个生命周期,其中内置的函数componentDidMount函数负责在组件显示后调用,延迟2s给data传递了本地数据,这样就有一个过了两秒数据才加载出来的感觉
通过上面的两步,页面一个纯静态的样子就出来了,过滤的功能还没有加。
然后作者提到了一个关键的概念,就是React中的props和state,他俩的区别在哪?什么时候使用state?
作者给出了一个解决的方法:
大概的翻译了一下原文,如上。这应该就是使用state的一个原则吧。
接下来,开始实现过滤的功能之前,根据上面的原则,我们思考我们要实现的这几个组件中,到底有哪些地方要用到state?
没错,一共3个:
1、整个表格的数据来源,正常情况下是从服务器请求的,所以使用state
2、SearchBar中的搜索框的输入值,因为是用户输入的,时刻在发生变化
3、SearchBar中的复选框
3、按照上面整理的,需要修改之前的两个组件
OK,完成。
完整代码可以到我的github上下载运行:https://github.com/lyc-chengzi/reactProject
后续新的例子会继续往上整合,并且用webpack来打包,希望大家一起学习
入门的一些准备工作可以参照官网的步骤,引入依赖的核心包,就不多说了,直接上官网的第二个具体例子,一个过滤产品列表的Table:https://facebook.github.io/react/docs/thinking-in-react.html
这篇文章主要介绍的并不是API的一些使用,而是向刚入门的同学介绍使用React设计组件时的一些思路,思考怎么样来更好的使用React。
1. 首先,要做的是这么个东西
一个很简单的table列表,带了一个搜索功能,只是界面比较简陋。。。(作者自己也调侃说这肯定是个糟糕的设计,哈哈)。鉴于此,使用bootstrap稍微规整了一下
2. 接着,作者分析了这个组件该怎么划分:要本着最小原则,实现单一功能得原则,划分了五个组件
每种颜色代表一个组件,最后组件的关系如下,很好理解:
FilterableProductTable
SearchBar
ProductTable
ProductCategoryRow
ProductRow
下面直接进入主题,来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来打包,希望大家一起学习
相关文章推荐
- Extjs5.1 柱状图动态加载
- jstree使用
- js刷新当页面
- JS 数字,金额 用逗号 隔开(数字格式化)
- rails AJAX方法 操作后需要执行js文件中命令的方法
- js拼接html多参数传递转义
- json数据转换
- Gulp Error: Cannot find module 'jshint/src/cli';
- 拼接json数据2种方法
- 写了 几个 json 生成小工具
- jsp
- YYKit - YYModel 使用方法
- js的原型prototype理解
- js解析json
- JSP 结构
- 前端代码编码和设计规范系列——JavaScript编程规范
- js正则表达式中的问号几种用法小结
- JS正则表达式的RegExp对象和括号的使用等需要注意的
- JavaScript constructor prototyoe
- 轻松5句话解决JavaScript的作用域