1. 父控件在不可知子控件的情况下的传值(映射)问题 ✅
2017/09/06
如果我们有如下控件 TimeControler
和 DigitTextGroup
TimeControler
用于接受Unix 时间戳,转换成为倒计时
DigitTextGroup
用于接受 分,秒,毫秒的值,并且按一定样式显示
差不多长这个样子
即所有的数据都必须要显示声明?
我所想做的就是让 TimeControler
来控制子控件时间,时间不断递加或者递减。
本例当中就是 DigitTextGroup
这个控件。如果把DigitTextGroup
写在TimeControler
里面当然可以,但是可复用性太差,不利于扩展
所以父控件如何与子控件进行交互,在不可知子控件的情况下?
1.1 初步构想
- 需要提供父控件与子控件的值映射关系,本例当中为把父控件的 Unix时间戳 转换成 分秒毫秒
1.2 类似的问题
- 比较接近的是这个 How to pass props to {this.props.children}
第一个方法主要做法是把子控件与子控件 props 的一起渲染,不符合当前需求
第二个方法亲测可用,如图下所示
1.3 魔改
使用1.2当中的第二个答案对 TimeController 修改
render() {
const {timestamp} = this.props;
return (
<View style={{...this.props.style}}>
{this.props.children}
</View>
);
}
改成
render() {
const {timestamp} = this.props;
return (
<View style={{...this.props.style}}>
{React.cloneElement(this.props.children, {min: 20, second: 10, milliSecond: 99})}
</View>
);
}
完美运行
现在唯一需要做的就是把 子控件的 props {min: 20, second: 10, milliSecond: 99}
单独抽取出来,因为父控件(TimeController
)并不知道子控件的 props 格式与数据结构。
// 首先定义子类(DigitTextGroup)需要的值映射
const binder = {
min: (date: Date) => date.getMinutes(),
second: (date: Date) => date.getSeconds(),
milliSecond: (date: Date) => this.ensureMilliSecond(date)
}
// 因为毫秒位只需要两位,所以做一下处理
ensureMilliSecond(date: Date) {
return Number.parseInt(date.getMilliseconds() / 10)
}
将从父类传入TimeController
的 值-Func 映射转换成键值对
makeProps(binders) {
const childProps = {}
for (b in binders) {
childProps[b] = binders[b](this.state.date)
}
return childProps
}
使用方法如下:
timeStep
为时间间隔,单位为msbinders
为子控件的映射(键即为子控件的自定义属性)timestamp
为未来的某个时间点,格式为 Unix 时间戳
DigitTextGroup
为一个显示时间的控件,PropsTypes 定义如下:
static propTypes: {
min: React.PropTypes.number,
second: React.PropTypes.number,
milliSecond: React.PropTypes.number
};
最后UI差不多长这个样子
UI 界面全都是DigitTextGroup
类进行定义,里面的值是通过父类TimeController
类进行控制
现在,TimeController
类就只负责定时器的相关功能,子控件只需要关注 UI 样式。
Github 地址 : https://github.com/react-io/rn-timer
网友评论