鉴于您的示例,在层上“向上”移动实现的要点是能够在应用程序的不同部分使用相同的计时器组件,其中 start() 每次的行为可能都不同。
组件本身无法知道每个特定的“开始”事件应该做什么,因为组件在任何时候都不应该知道它是如何使用的。
将回调视为事件处理程序,调用者在其中传递事件发生时应执行的操作
这实际上强制执行 DRY,因为您需要 1 个计时器(启动、暂停、停止、计时器到达的逻辑可能等等),然后每个调用者在这些事件发生时连接他想做的事情。
如果你想到 React 本身的结构,以及它的生命周期事件,它就是一回事。例如,“ComponentDidMount”与计时器的“开始”没有什么不同,只是上下文不同。概念思想是一样的
编辑:重要的是要考虑在您的组件中为每个人保持固定的内容以及应该可配置的内容。
例如,您的计时器将始终每秒滴答一次,对吗?因此,时间跟踪部分对于您的应用程序将始终保持不变,它应该驻留在组件中。组件应该有一个 Start,Pause,Stop 定义的方法集,因为 stop 总是会停止计数,start 总是会恢复它。
但是您需要公开一个 OnStart、OnStop、OnPause,以便调用者可以使用您的计时器挂钩他们需要的逻辑。我不知道我能不能解释得足够好......
编辑 2:
例如检查下面的计时器的 Start 方法:
function Start(){
// set the interval here or wtver way you will have to measure ticks
// ...
// ...
if(this.props.OnStart)
this.props.OnStart();
}
现在当然调用者将不负责实现实际的滴答声(尽管有一天有人可能会来请求一个与以光速或其他东西旅行的人相关的跟踪器,所以滴答声也可以配置...... ),但如果他们确实需要在 start 事件上有一个挂钩,并且他们会这样做,那么您可以通过这种方式实现它。
组件不知道回调函数的作用(业务逻辑向上移动),但是调用者现在不关心通用的“每秒一次滴答”
编辑 3:
好的,所以.. 如果单击按钮,我们将启动计时器,然后调用道具给出的任何钩子
function OnEveryClick(){
// here you will write anything you want your component to do every time the button is clicked, regardless of who is the caller, like our previous Start method
this.Start();
}
function ButtonClicked(){
// first you call your method every time
this.OnEveryClick();
// then if the caller also wants to do some stuff, you evaluate their function aswell
if(this.props.OnSubmit)
this.props.OnSubmit();
}
然后在渲染上你做这样的事情
<button onClick={this.ButtonClicked.bind(this)}>