1 回答
TA贡献1775条经验 获得超11个赞
一个网站,从功能上划分,都能整理出一个个细小的组件,比如一个头部,一个按钮,一个banner,那么怎样才能写好一个可以在多个页面共享数据或私有状态的组件呢?
以一个移动端常见的header头部为例,左边是返回按钮,有的还带有文字,中间是标题文字,右边可能有图片或者文字。
<div>
<i>返回按钮</i>
<span>标题</span>
<img src="" />
</div>
返回按钮
返回文字(backText)
标题(title)
图片或文字(icon)
返回点击事件
图片或文字点击事件(handleClick)
背景样式
文字样式
这8个基本因素是所有头部都共用的,有的可有,有的可无,为了保证每个网页都能调用同一个头部组件,又要确保文本和事件还有样式可以自定义。将可变的因素提取出来,通过变量的方式传入组件。
在react中,传递变量用this.props。
const {backText, title, icon, handleClick} = this.props
let _backText = backText || false,
_title = title || false,
_icon = icon || false
return (
<div>
<i onClick={handleClick}>{_backText}</i>
<span>{_title}</span>
<img src={_icon} />
</div>
)
在父容器里面调用header组件的用法和安卓上类似,都是通过参数初始化配置。
handleClick(){
//注意,使用context的童鞋,需要定义contextType才可以,不然会报错
this.context.router.go(-1)
}
render() {
return (
<Header
backText="返回首页"
title="个人中心"
icon={imgUrl}
handleClick={this.handleClick}
/>
)
}
static contextTypes = {
router: React.PropTypes.object.isRequired
};
通过简单的配置,就能构造更多可复用的组件,组件拆的越细,复用的程度就越高,这里没有做传入样式的例子,但是样式的初始化也是类似的方法。
还有常用的组件,如弹框:
<div>
<p>标题</p>
<p>中间内容,可以是text或者带有多个标签样式的text</p>
<p>
<a>左边按钮,通常叫做取消</a>
<a>右边按钮,通常叫做确认</a>
</p>
</div>
跟header组件实现一样,首先把可变的数据部分和事件抽象出来。
标题(title)
中间内容(content)
左边按钮文本(leftText)
右边按钮文本(rightText)
左边按钮的点击事件(leftClick)
右边按钮的点击事件(rightClick)
render() {
const {title, content, leftText, rightText, leftClick, rightClick} = this.props
//这里再做一次判断空数据或者为定义数据的处理,没人能保证传递进来的参数一定存在或者一定不为空。
return (
<div>
<div>{title}</div>
<div>{content}</div>
<div>
<a onClick={leftClick}>{leftText}</a>
<a onClick={rightClick}>{rightText}</a>
</div>
</div>
)
}
父容器组件调用弹框组件
leftClick() {
//左边按钮事件
}
rightClick() {
//右边按钮事件
}
render() {
const content = <p><span>提示语1</span><span>提示语2</span></p>
return (
<BombBox
title="弹框标题"
content={content}
leftText="取消"
rightText="确认"
leftClick={this.leftClick}
rightClick={this.rightClick}
/>
)
}
到这里就结束了吗?不是的,我们知道,还有一个东西叫做state,react中,控制弹框的出现和消失,通过state来控制,而我这里要讲的是react和redux结合使用,发送一个dispacth action改变state的状态,使得弹框出现和隐藏。
leftClick() {
//左边按钮事件,隐藏弹框,调用一个action函数,该action函数会改变reducer中state的状态
this.props.BombAction(false)
}
rightClick() {
//右边按钮事件,点击跳转到下一个页面的路由
this.context.router.push(`/nextRoute`)
//这里还需要做一件事,点击确定后,首先要清除掉弹出框的true状态,恢复成false,避免在其他页面共用该组件的弹出框还没点击出发事件就已经弹出来了。这一步也可以在BombBox组件内部用componentWillUnmount()来触发。
this.props.BombAction(false)
}
render() {
const content = <p><span>提示语1</span><span>提示语2</span></p>
//在叫做global(全局)的reducer定义1个state参数BombStatus,表示弹框的状态,true为显示弹框,false为隐藏弹框。默认是false
const {BombStatus} = this.props.global
return (
<div>
{
BombStatus ?
<BombBox
title="弹框标题"
content={content}
leftText="取消"
rightText="确认"
leftClick={this.leftClick}
rightClick={this.rightClick}
/> : false
}
</div>
)
}
static contextTypes = {
router: React.PropTypes.object.isRequired
};
到这里,一个基本的可复用弹框组件就完成了,在任意一个页面,调用该组件的方法都是一样的,即发送一个action去改变state的状态,然后让弹框组件加载进来。隐藏也是改变state的状态。
还有很多的例子,比如表格,li列表(常见在分页组件上)等等。。。。
无论是一个简单的组件,还是一个复杂的组件,都要记住一点,先抽象出来可变的内容和事件,然后通过action去控制组件的state状态,不要在组件内部去用setState和getState,前提是你也是用redux来管理state。
组件是个view,要保证组件的纯净,这样服用的程度就会更高。
- 1 回答
- 0 关注
- 623 浏览
添加回答
举报