1.首先我们需要一个事件类BaseEvent,我们在实现对象级别事件用到它的地方是:在触发时把这个类的实例作为事件处理器的参数传递进去,在同一个事件中的多个事件处理器间,是共享这个实例的。
BaseEvent类的代码如下:
<?php
namespace tank\base;
class BaseEvent extends BaseObject
{
public $eventName;
public $sender;
public $onData = [];
public $stopFlag = false;
}
需要注意的是,在实现对象级别的事件时,我们需要的BaseEvent就只有这些。在实现类级别的事件时,会添加其他代码,我们到时候再说回。
2.在Component类中,我们需要一个保存已经绑定的事件的数据结构。
该数据结构是这么设计的:
$eventMap;
[
'eventName1' => [
'handler1',
'handler2'
],
'eventName2' => [
'handler2',
'handler3'
]
]
以数组的键作为事件名,数组值是事件处理器,事件处理器的执行是顺序执行的。
3.绑定事件的方法,参数有事件名,事件处理器,绑定时数据和事件处理器的运行次序
public function bindEvent($eventName, $eventHandler, $onData = [], $handlerSequence = -1)
{
$handlerList = isset($this->eventMap[$eventName]) ? $this->eventMap[$eventName] : [];
$insertValue = [$eventHandler, $onData];
$this->eventMap[$eventName] = Tank::appendElementByPosition($handlerList, $handlerSequence, $insertValue);
}
4.解除事件绑定的方法
public function unbindEvent($eventName, $eventHandler = null)
{
$result = false;
if (empty($this->eventMap[$eventName])) {
$result = false;
} else if (is_null($eventHandler)) {
unset($this->eventMap[$eventName]);
$result = true;
} else {
$tmpEventMap = $this->eventMap[$eventName];
foreach ($tmpEventMap as $key => $value) {
if ($eventHandler == $value[0]) {
unset($this->eventMap[$eventName][$key]);
$result = true;
}
}
if ($result) {
$this->eventMap[$eventName] = array_values($this->eventMap[$eventName]);
}
}
return $result;
}
5.触发事件的方法
public function triggerEvent($eventName, BaseEvent $eventObject = null)
{
if (!empty($this->eventMap[$eventName])) {
if (is_null($eventObject)) {
$eventObject = new BaseEvent();
}
if (is_null($eventObject->sender)) {
$eventObject->sender = $this;
}
$eventObject->stopFlag = false;
$eventObject->eventName = $eventName;
foreach ($this->eventMap[$eventName] as $value) {
$currentHandler = $value[0];
$currentData = $value[1];
$eventObject->onData = $currentData;
call_user_func($currentHandler, $eventObject);
if ($eventObject->stopFlag) {
break;
}
}
}
BaseEvent::triggerClassEvent($this, $eventName, $eventObject);
}
最后一行的是类级别事件的触发,现在可以不用管,下次我们再说回。
ok,今儿个先到这,欲知后事如何,且听下回分解……
github源码:https://github.com/2lovecode/tank