关于React的思考
来源:互联网 发布:php缓存技术有哪些 编辑:程序博客网 时间:2024/06/06 12:37
关于React的思考
我们从一个可搜索的产品表来领会一下React的工作流程。
这是应用的完成状态JSFiddle代码地址。
这个产品UI如下
我们的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"}];
有产品分类,产品价格,是否还有库存,和产品名。
Step 1:把UI分解成组件结构
首先把整个UI分解成不同的组件,那么怎么知道哪个部分或者哪些部分作为一个组件呢?当我们写一个函数或者对象的时候会怎么做呢,答案就是单一职责原则,让一个组件做好一件事就可以了。还有就是我们可以根据数据模型来分割组件,数据模型和UI表现往往表现一致。下面是我们对产品搜索表进行的UI组件划分。
包括:
- FilterableProductTable(orange):包含了整个应用
- SearchBar(blue):接收用户的输入
- ProductTable:根据用户输入显示过滤后的产品数据
- ProductCategoryRow:显示一组产品的分类目录
ProductRow:每行显示一种商品
在ProductTable中还有两个不是一个组件的单词,Name和Price,这里见仁见智,因为我们觉得它们是产品表的一部分,所以把它们归在了ProductTable里面。
到这里组件结构就很清晰了:FileterableProductTable
- SearchBar
- ProductTable
- ProductCategoryRow
- ProductRow
Step2:用React创建一个静态版本
JSFiddle地址
有了组件结构之后最简单的就是构建一个静态版本,那意味着你要把你的数据硬编码在程序里,而且缺少互动,显然不是我们追求的结果。所以我们应该构建一个动态版本,增加互动和趣味性,同时也能减少你的编码量。
在静态版本里,我们通过复用组件模块和通过props属性传递数据。如果你对state属性熟悉的话,你应该知道它就是为了互动性而保留的,意思就是如果你构建的不是一个动态的应用,你最好不要请state出来,如果你对props和state还不熟悉的话,参考官方文档(自己搜吧)。
通常构建应用的方向有两种:自顶向下和自底向上。一般来说,简单的引用用自顶向下会简单一点,而复杂的应用我们建议你用自底向上的方式,这样便于你测试你写的底层组件。
Step3:在必须用state的时候再去请他
为了让你的应用UI变得互动起来,应用应该能用嗅探到数据的变化从而做出反应动作。而React中的state就是为了这个目的出生的。
为了保证你的应用精准,首先应该考虑的事情就是避免滥用state,在必须使用state的地方再去使用它。原则就是DRY:Don’t repeat yourself。那么怎么判定某个数据中必须使用state呢,很简单,问他三个问题:
- 这个数据是通过props从父组件传递的吗?如果是,他不是stata
- 这个数据不会随着时间改变?如果是,他不是state
- 这个数据可以通过其他的state或者props数据计算出来?如果是,他不是state
在这个查找产品的例子中,我们有这么几个数据:
- 产品的原始列表
- 用户在搜索框输入的文本
- checkbox的值
- 产品的过滤列表
那么来看看,产品的原始列表是从ReactDOM.render中从父组件中传递的,而且一般也不会改变,那他不是state。用户输入的文本和checkbox的值好像是state,因为它是用户决定的而且不能计算出来。产品的过滤列表可以通过用户输入的文本和checkbox的值计算出来,所以他不是state。所以我们有两个state数据:
- 用户输入的搜索文本
- 用户输入的checkbox值
Step4:让你的state数据活过来
好的,当你确定了哪些数据必须是state之后,下一件要确认的事就是哪些组件要拥有这些数据。这也是大部分新手不容易理解的地方。跟紧下面这些步骤:
对于你的应用里的每一个state数据:
- 找出所有要基于这个数据render一些东西的组件
- 找到这些组件的一个共同父组件
- 这个共同父组件以及这个父组件之上的每个组件都应该拥有这个state
- 如果你不是很清楚某个组件是否可以拥有这个state,最简单的方式就是创造一个新的组件包含这个state数据,而把这个新组件添加公共父组件(前面提到的那个)之上。
现在让我们在这个应用里使用这个策略:
- ProductTable要根据用户搜索文本过滤产品列表,SearchBar要显示用户输入文本和复选框。
- 这两个组件的共同父组件是FilterableProductTable
- 理论上讲FilterableProductTable应该拥有这两个state属性
所以首先我们在FilterableProductTable中添加getInitialState
方法初始化state为`{filterText:”,inStockOnly:false},然后把这两个state数据作为props传给ProductTable和SearchBar让他们做自己的render。
JSFiddle地址
你可以将getInitialState中的filterText改为’ball’运行,就可以看到过过滤后的结果了。
Step5:反向数据流
在这之前你会发现你不能在输入框中输入文字或者点击复选框,因为我们已经指定了它们的value等于一个state数据,而这个数据是从父组件中传递下来的。所以不能改变,那怎么办呢?答案是在我们输入的同时更新父组件里的state数据,子组件的state也会自动更新,那么输入框和复选框的value也会自动改变。
JSFiddle代码地址这是整个应用的完全状态。
在这之前,我们的应用的数据流向都是从父组件流向子组件进行render,现在我们来尝试另一种数据流:最深处的SearchBar数据的改变向上反映给FilterableProductTable更新state。
我们首先在FilterableProductTable中定义了一个更新state的函数,其中调用了React内置的setState函数,注意这个函数可以改变state属性,在这个应用中我们改变了过滤字符串和只显示有库存,如下:
handleUserInput: function(filterText, inStockOnly) { this.setState({ filterText: filterText, inStockOnly: inStockOnly });},<SearchBar filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} onUserInput={this.handleUserInput}/>
然后把这个函数作为props的一个属性传给SearchBar。然后在SearchBar层面上我们给input标签设置onChange函数(注意React中给元素添加事件命名都为驼峰命名式)。如下:
handleChange: function() { this.props.onUserInput( this.refs.filterTextInput.value,//快速定位到ref this.refs.inStockOnlyInput.checked );}//render()<form> <input type="text" placeholder="Search..." value={this.props.filterText}//会根据父组件传下来的state属性动态改变。 ref="filterTextInput" onChange={this.handleChange} /> <p> <input type="checkbox" checked={this.props.inStockOnly} ref="inStockOnlyInput" onChange={this.handleChange} /> {' '} Only show products in stock </p> </form>
这个onChange函数做了什么呢,调用了传递下来的handlerUserInput函数,然后在FilterableProductTable层面上完成了state的更新。
setState()会造成state的改变,而state变化的时候包含它的组件会发生自动重绘,而重绘过程是依据改变新的state数据的,这样我们就完成了动态更新,很简单,是不是?
总结一下
Step 1:把UI分解成组件结构,注意UI和数据模型趋于一致
Step2:用React创建一个静态版本,没有数据交互,像一张照片
Step3:确定必要的state数据,state不能滥用
Step4:确定包含state数据的组件,一般都包含在公共父组件中
Step5:反向数据流,根据子组件中的变化事件更新父组件中的state数据
- 关于React的思考
- 关于redux+react的一些思考
- React Navtive 的思考
- 【react学习】关于react框架使用的一些细节要点的思考
- 【react学习】关于react框架使用的一些细节要点的思考
- 【react学习】关于react框架使用的一些细节要点的思考
- 【react】关于react框架使用的一些细节要点的思考
- 关于思考的思考
- 关于思考的思考
- react状态管理的思考
- 12.React中文之对React的思考
- React实战-ReactJS+Redux的思考
- 浅谈React构建项目的思考过程
- 关于blog的思考。
- 关于克隆技术的思考
- 关于爱的思考
- 关于p2p的思考
- 关于编码的思考
- 洛谷 P1341无序字母对
- 嵌入式linux基础教程第二版 第二章
- 使用EA画ER图并导出为图片
- 源码解析
- QT5日志功能(qDebug、qWarnng、qCritical、qFatal)
- 关于React的思考
- codeforces731E Funny Game(DP)
- progressbar 自定义 分缓存层 未缓存层 已下载层
- opencv检测绿色物体(高8cm,宽15cm)
- 25.Native和Html5的交互(在anroid中使用html5,实现UI交互和数据显示)
- 日常心得 2016-10-20
- 超级喜欢老罗,2016发布了新手机
- React-建立实时评论应用
- leetcode-410. Split Array Largest Sum