本文主要思考的问题是如何设计组件,react 库设计的那么灵巧,确定不是用来作笨重的东西~html
我将会用 截图 + 简述文字 + 精简代码
来讲明前端
了解组件设计几个参考点:react
状态管理
能够分为 有状态组件
无状态组件
图解说明git
React.Component
形式建立用来管理应用数据,如业务上,首页须要数据有:github
代码示例json
class MyComponent extends Component { constructor(props) { super(props) this.state = { 推荐分类列表:[], 推荐广告列表:[], 推荐商品列表:[] } } render() { return <首页>...</首页> } }
这种组件本身不维护 状态,数据靠属性传入redux
代码示例segmentfault
function Element(props) { let val = props.val return <div>组件 - ...</div> }
职能
划分为 容器组件
操做组件
展现组件
图解说明数组
这类组件自己是一个有状态组件,像一个舞台把你们都呈现上去, 把数据用 属性
方式传下去,而后子组件用 事件
方式把数据返回react-router
像上面这个商品搜索业务
代码示例
class Container extends Component { constructor(props) { super(props) this.state = { 搜索关键字: '手机壳', 排序: '综合', 商品列表: [] } } render() { return ( <div> <搜索栏 关键字={this.state.搜索关键字} onChange={...} /> <列表控制栏 排序={this.state.排序} onChange={...} /> <商品列表 商品列表={this.state.商品列表} onChange={...} /> </div> ) } }
处理交互操做,好比 搜索框、用户注册登陆、购物车、文章编辑、拍图、上传
图解中的搜索框,接收 属性
关键字
产生的新数据 事件
方式返回容器组件
代码示例
function SearchInput(props) { let 关键字 = props.关键字 return ( <div> <input type="text" value={关键字} onKeyDown={props.onChange} placeholder="输入 ...... ↩" /> </div> ) }
这种就更纯粹了,只接收 属性
数据,用来展现
图解中的商品列表,接收 属性
商品列表
代码示例
function SearchInput(props) { let 商品列表 = props.商品列表 return ( <div> {商品列表.map((item, index) => ( <商品项 key={item.id} 商品信息={item} /> ))} </div> ) }
其中商品信息
组件也是一个展现组件
, 尽量的把组件拆分
其实就是在一个容器组件上,摆放了一个 控制组件
和一个 展现组件
图解说明
咱们动手写一下
代码
function InputView(props) { return ( <div> <input type="text" onKeyDown={props.onChange} placeholder="输入 ...... ↩" /> </div> ) }
处理 onKeyDown
消息,返回给父容器
代码
function ListView(props) { return ( <ol> {props.datas && props.datas.map((item, index) => ( <li key={index.toString()}>{item}</li> ))} </ol> ) }
map
循环打印数据列表
代码
class ContainerView extends Component { constructor(props) { super(props) this.state = {list: []} this.handleChange = this.handleChange.bind(this) } handleChange(e) { if (e.keyCode === 13) { const value = e.target.value e.target.value = '' this.setState((state, props) => { let list = state.list list.push(value) return {list} }) } } render() { return ( <div> <InputView onChange={this.handleChange} /> <ListView datas={this.state.list} /> </div> ) } }
e.keyCode === 13
表示一直监控到输入回车,开始更新状态
https://codepen.io/ducafecat/...
这个例子加入数据双向绑定功能,这在表单操做中用的很频繁
图解说明
仍是用代码说明
代码
class InputView extends Component { constructor(props) { super(props) this.form = props.form // 父容器 state.form this.sync = props.sync // 父容器 sync this.handleChange = this.handleChange.bind(this) } handleChange(e) { let name = e.target.attributes.name.value let value = e.target.value this.sync({name, value}) } render() { return ( <ul> <li> <input name="input" type="text" value={this.form.input} onChange={this.handleChange} /> </li> <li> <textarea name="textarea" value={this.form.textarea} onChange={this.handleChange} /> </li> <li> <select name="select" value={this.form.select} onChange={this.handleChange} > <option value="">---</option> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option value="coconut">Coconut</option> <option value="mango">Mango</option> </select> </li> </ul> ) } }
props.form
是容器传入的表单数据,结构以下{ input: '', textarea: '', select: '' }
按控件名称 key / val
结构
props.sync
是回传父容器的事件,相应代码以下handleChange(e) { let name = e.target.attributes.name.value let value = e.target.value this.sync({name, value}) }
能够发现回传的是 {控件名, 控件值}
,这里是简写(键、值 名相同时能够写一个),完整格式是
{ name: name, value: value }
代码
function ListView(props) { let form = props.form let list = [] for (let key in form) { list.push({ key, value: form[key] }) } return ( <ul> {list && list.map((item, index) => ( <li key={index.toString()}> {item.key} - {item.value} </li> ))} </ul> ) }
这里作展现就简单了,接收到属性 form
后,格式化成数组 list
,而后 map
打印
代码
class ContainerView extends Component { constructor(props) { super(props) this.state = {form: {input: '', textarea: '', select: ''}} this.handleSync = this.handleSync.bind(this) } handleSync(item) { this.setState((prevState, props) => { let form = prevState.form form[item.name] = item.value return {form} }) } render() { return ( <div> <InputView sync={this.handleSync} form={this.state.form} /> <ListView form={this.state.form} /> </div> ) } }
handleSync
中 form[item.name] = item.value
动态更新 key / value
达到更新 state
https://codepen.io/ducafecat/...
经过学习本章后,你们写具体功能代码前,能够先作下 UI组件架构设计
这个没有那么神秘,就是描述下有哪些组件、他们之间如何组装
若是大脑中抽象的不清楚,能够借助原型工具设计,本身能看懂就行,不然边写边设计容易乱掉
设计完成后,过几遍没啥问题了,再编写具体功能