关联阅读
十一、逐行阅读Yii2.0.43源码_Yii框架文件Component.php(1)
十二、逐行阅读Yii2.0.43源码_Yii框架文件Component.php(2)
十三、逐行阅读Yii2.0.43源码_Yii框架文件Component.php(3)
十四、逐行阅读Yii2.0.43源码_Yii框架文件Component.php(4)
目录
一、hasEventHandlers方法,返回$name是否有绑定了对应的事件处理程序,搜索顺序:
一、hasEventHandlers方法,返回$name是否有绑定了对应的事件处理程序,搜索顺序:
1.通配符事件
2.普通事件
3.类级别事件
/**
* 返回$name是否有绑定了对应的事件处理程序
*/
public function hasEventHandlers($name)
{
//1. 模式匹配
$this->ensureBehaviors();
foreach ($this->_eventWildcards as $wildcard => $handlers) {
if (!empty($handlers) && StringHelper::matchWildcard($wildcard, $name)) {
return true;
}
}
return
//2. 事件数组查找
!empty($this->_events[$name]) ||
//3.类级别事件
Event::hasHandlers($this, $name);
}
二、on方法,绑定事件
1. $append为true,将新事件追加事件列表末尾
2. $append为false,将新事件插入事件列表开头
/**
* 绑定事件
* $append为true,将新事件追加事件列表末尾
* $append为false,将新事件插入事件列表开头
*/
public function on($name, $handler, $data = null, $append = true)
{
$this->ensureBehaviors();
// 1. 事件名称存在 '*',是一个通配符事件
if (strpos($name, '*') !== false) {
if ($append || empty($this->_eventWildcards[$name])) {
$this->_eventWildcards[$name][] = [$handler, $data];
} else {
array_unshift($this->_eventWildcards[$name], [$handler, $data]);
}
return;
}
//2. 普通事件
if ($append || empty($this->_events[$name])) {
$this->_events[$name][] = [$handler, $data];
} else {
array_unshift($this->_events[$name], [$handler, $data]);
}
}
三、off方法,解绑事件
1. $_events和$_eventWildcards不存在$name,直接返回false
2. $handler为null,删除$name对应的所有事件
3.普通事件,遍历$name事件列表,移除$handler
4.通配符事件
/**
* 解绑事件
*/
public function off($name, $handler = null)
{
$this->ensureBehaviors();
//1. $_events和$_eventWildcards不存在$name,直接返回false
if (empty($this->_events[$name]) && empty($this->_eventWildcards[$name])) {
return false;
}
//2. $handler为null,删除$name对应的所有事件
if ($handler === null) {
unset($this->_events[$name], $this->_eventWildcards[$name]);
return true;
}
$removed = false;
// 3.普通事件,遍历$name事件列表,移除$handler
if (isset($this->_events[$name])) {
foreach ($this->_events[$name] as $i => $event) {
if ($event[0] === $handler) {
unset($this->_events[$name][$i]);
$removed = true;
}
}
if ($removed) {
//重新索引,赋值
$this->_events[$name] = array_values($this->_events[$name]);
return true;
}
}
// 4.通配符事件
if (isset($this->_eventWildcards[$name])) {
foreach ($this->_eventWildcards[$name] as $i => $event) {
if ($event[0] === $handler) {
unset($this->_eventWildcards[$name][$i]);
$removed = true;
}
}
if ($removed) {
$this->_eventWildcards[$name] = array_values($this->_eventWildcards[$name]);
// 删除空通配符
if (empty($this->_eventWildcards[$name])) {
unset($this->_eventWildcards[$name]);
}
}
}
return $removed;
}
四、trigger方法,触发事件
1. 合并通配符事件和普通事件处理函数
2.遍历事件处理函数,直到事件被处理,返回
3.类级别事件触发
/**
* 触发事件
*/
public function trigger($name, Event $event = null)
{
$this->ensureBehaviors();
//1. 合并通配符事件和普通事件处理函数
$eventHandlers = [];
foreach ($this->_eventWildcards as $wildcard => $handlers) {
if (StringHelper::matchWildcard($wildcard, $name)) {
$eventHandlers = array_merge($eventHandlers, $handlers);
}
}
if (!empty($this->_events[$name])) {
$eventHandlers = array_merge($eventHandlers, $this->_events[$name]);
}
//2.遍历事件处理函数,直到事件被处理,返回
if (!empty($eventHandlers)) {
if ($event === null) {
$event = new Event();
}
if ($event->sender === null) {
$event->sender = $this;
}
$event->handled = false;
$event->name = $name;
foreach ($eventHandlers as $handler) {
$event->data = $handler[1];
call_user_func($handler[0], $event);
// 如果事件已被处理,则停止进一步处理
if ($event->handled) {
return;
}
}
}
// 3.类级别事件触发
Event::trigger($this, $name, $event);
}
总结:
阅读了4个事件相关的方法:
- hasEventHandlers是否有绑定了对应的事件处理程序
- on 绑定事件
- off 解绑事件
- trigger 触发事件