接上次的组件(component)代码:

 /**
      * Returns a list of behaviors that this component should behave as.
      * 定义该对象中要用到的 behavior,返回一个行为列表
      * Child classes may override this method to specify the behaviors they want to behave as.
      *
      * 行为配置数组格式如下:
      *
      * ```php
      * 'behaviorName' => [
      *     'class' => 'BehaviorClass',
      *     'property1' => 'value1',
      *     'property2' => 'value2',
      * ]
      * ```
      * Behaviors declared in this method will be attached to the component automatically (on demand).
      * 定义该对象中要用到的 behavior
      * @return array 行为配置.
      */
     public function behaviors()
     {
         return [];
     }

     /**
      * Returns a value indicating whether there is any handler attached to the named event.
      * 判断 _events 中的一个 event 是否具有事件处理程序
      * @param string $name 事件名
      * @return boolean whether there is any handler attached to the event.
      */
     public function hasEventHandlers($name)
     {
         $this->ensureBehaviors();
         //短路写法,判断调用_events中是否有$name事件,没有直接返回false,否则,调用Event类中的的方法判断是否有处理程序
         return !empty($this->_events[$name]) || Event::hasHandlers($this, $name);
     }

     /**
      * Attaches an event handler to an event.
      * 添加事件处理程序到事件
      * The event handler must be a valid PHP callback. The following are
      * some examples:
      * 事件处理程序必须是有效的PHP回调函数,方便内置方法call_user_fucn()调用 ,例如:
      * ```
      * function ($event) { ... }         // 匿名函数
      * [$object, 'handleClick']          // 以数组形式表示的对象的方法
      * ['Page', 'handleClick']           // 静态方法
      * 'handleClick'                     // 全局函数,只写函数名
      * ```
      *
      * The event handler must be defined with the following signature,
      * 时间处理程序的定义格式:
      * ```
      * function ($event)
      * ```
      *
      * where `$event` is an [[Event]] object which includes parameters associated with the event.
      * `$event`是一个包含于event相关联的[[Event]]对象
      * @param string $name 事件名
      * @param callable $handler 事件处理函数
      * @param mixed $data the data to be passed to the event handler when the event is triggered.
      * When the event handler is invoked, this data can be accessed via [[Event::data]].
      * @param boolean $append whether to append new event handler to the end of the existing
      * handler list. If false, the new handler will be inserted at the beginning of the existing
      * handler list.
      * @see off()
      */
     public function on($name, $handler, $data = null, $append = true)
     {
         $this->ensureBehaviors();//确保所有的行为都加载到组件中
         if ($append || empty($this->_events[$name])) {//$append 判断是否添加到事件(event)的后面,且确保_events中有该事件
             $this->_events[$name][] = [$handler, $data];//将事件处理程序和参数添加到event数组中
         } else {//否则,添加到event数组的前面
             array_unshift($this->_events[$name], [$handler, $data]);
         }
     }

     /**
      * Detaches an existing event handler from this component.
      * This method is the opposite of [[on()]].
      *
      * [[on()]]方法的反方法,用于删除事件处理程序
      *
      * @param string $name 事件名
      * @param callable $handler 事件处理程序
      * 如果$handler 为空,清除该事件的所有时间处理程序
      * @return boolean if a handler is found and detached
      * @see on()
      */
     public function off($name, $handler = null)
     {
         $this->ensureBehaviors();//确保所有的行为都加载到组件中
         if (empty($this->_events[$name])) {//如果_events中没有该事件,也就是事件不存在
             return false;                 //返回false
         }
         if ($handler === null) {//如果事件处理程序为空
             unset($this->_events[$name]);//清除该事件的所有事件处理程序
             return true; //返回true
         } else {
             $removed = false; //删除标记
              //否则遍历该事件 根据on()方法的格式可以知道,$event[0]是事件处理程序,$event[1]是数据
             foreach ($this->_events[$name] as $i => $event) {
                 if ($event[0] === $handler) {//判断事件处理程序是否符合
                     unset($this->_events[$name][$i]);//删除该事件处理程序
                     $removed = true;
                 }
             }
             if ($removed) {//判断是否删除成功
                 //如果删除成功,调用array_values方法重新赋值,格式化索引
                 $this->_events[$name] = array_values($this->_events[$name]);
             }
             return $removed;//返回删除成功标记
         }
     }

     /**
      * Triggers an event.
      * This method represents the happening of an event. It invokes
      * all attached handlers for the event including class-level handlers.
      *
      * 触发器方法
      *
      * @param string $name 事件名
      * @param Event $event  事件参数. 如果未设置,一个默认的 [[Event]] 对象将被创建.
      */
     public function trigger($name, Event $event = null)
     {
         $this->ensureBehaviors();
         if (!empty($this->_events[$name])) {
             if ($event === null) {
                // 构建Event对象,为传入到handler函数中做准备
                 $event = new Event;
             }
             if ($event->sender === null) {
                 $event->sender = $this;
             }
             $event->handled = false;
             $event->name = $name;
             foreach ($this->_events[$name] as $handler) {
                 //遍历_events取得处理程序名和数据
                 $event->data = $handler[1];//给[[Event]] 的data属性赋值
                 call_user_func($handler[0], $event);//通过内置函数call_user_func()调用事件处理函数,$event作为参数
                 // stop further handling if the event is handled
                 // 事件是否被handle,当handled被设置为true时,执行到这个event的时候,会停止,并忽略剩下的event--不太明白,以后追加吧
                 if ($event->handled) {
                     return;
                 }
             }
         }
         // invoke class-level attached handlers
         //[[Event]] 的静态方法,触发类级别的事件处理程序
         Event::trigger($this, $name, $event);
     }

     /**
      * Returns the named behavior object.
      * 获取行为类
      * @param string $name the behavior name
      * @return null|Behavior the behavior object, or null if the behavior does not exist
      */
     public function getBehavior($name)
     {
         $this->ensureBehaviors();
         return isset($this->_behaviors[$name]) ? $this->_behaviors[$name] : null;//_behaviors中的行为类存在,返回行为类名,否则返回空
     }

     /**
      * Returns all behaviors attached to this component.
      *
      * 获取所有的行为类
      * @return Behavior[] list of behaviors attached to this component
      */
     public function getBehaviors()
     {
         $this->ensureBehaviors();
         return $this->_behaviors;//直接返回了_behaviors
     }

     /**
      * Attaches a behavior to this component.
      * 添加一个行为到组件
      * 通过提供的配置文件创建一个Behavior对象,通过调用 [[Behavior::attach()]] 方法添加行为到组件.
      * @param string $name the name of the behavior.
      * @param string|array|Behavior $behavior 行为配置,可选项如下:
      *
      *  - 一个行为类
      *  - 一个字符串形式的指定行为类
      *  - 一个配置文件数组,通过调用[[Yii::createObject()]] 创建一个行为对象.
      *
      * @return Behavior the behavior object
      * @see detachBehavior()
      */
     public function attachBehavior($name, $behavior)
     {
         $this->ensureBehaviors();
         return $this->attachBehaviorInternal($name, $behavior);
     }

     /**
      * Attaches a list of behaviors to the component.
      * 添加行为到组件
      * 行为类通过行为名索引,且必须是一个 [[Behavior]] 对象指定的行为类或者一个配置数组
      *
      * @param array $behaviors list of behaviors to be attached to the component
      * @see attachBehavior()
      */
     public function attachBehaviors($behaviors)
     {
         $this->ensureBehaviors();
         foreach ($behaviors as $name => $behavior) {
             $this->attachBehaviorInternal($name, $behavior);
         }
     }

     /**
      * Detaches a behavior from the component.
      * 从组件解除行为
      * The behavior's [[Behavior::detach()]] method will be invoked.
      * 实现方式是调用Behavior类中的detach()方法
      * @param string $name the behavior's name.
      * @return null|Behavior the detached behavior. Null if the behavior does not exist.
      */
     public function detachBehavior($name)
     {
         $this->ensureBehaviors();
         if (isset($this->_behaviors[$name])) {
             $behavior = $this->_behaviors[$name];
             unset($this->_behaviors[$name]);
             $behavior->detach();
             return $behavior;
         } else {
             return null;
         }
     }

     /**
      * Detaches all behaviors from the component.
      * 解除所有的行为
      */
     public function detachBehaviors()
     {
         $this->ensureBehaviors();
         foreach ($this->_behaviors as $name => $behavior) {
             $this->detachBehavior($name);
         }
     }

     /**
      * Makes sure that the behaviors declared in [[behaviors()]] are attached to this component.
      * 确保定义的行为都被添加到组件
      */
     public function ensureBehaviors()
     {
         if ($this->_behaviors === null) {// 如果$this->_behaviors为空
             $this->_behaviors = [];
             foreach ($this->behaviors() as $name => $behavior) {//遍历$this->behaviors()中的behaviors,并存储到$this->_behaviors数组中
                 $this->attachBehaviorInternal($name, $behavior);
             }
         }
     }

     /**
      * Attaches a behavior to this component.
      *  私有方法  添加一个行为到组件
      * @param string|integer $name 行为名. 如果是整数,说明该行为是匿名的
      * @param string|array|Behavior $behavior the behavior to be attached
      * @return Behavior the attached behavior.
      */
     private function attachBehaviorInternal($name, $behavior)
     {
         if (!($behavior instanceof Behavior)) {
             // $behavior不是Behavior对象,就认为是配置,通过它创建一个
             $behavior = Yii::createObject($behavior);
         }
         if (is_int($name)) {//行为名师整数
             $behavior->attach($this);//绑定行为到组件
             $this->_behaviors[] = $behavior;
         } else {
             if (isset($this->_behaviors[$name])) {
                 // 如果有同名的行为存在就先解绑掉
                 $this->_behaviors[$name]->detach();
             }
             $behavior->attach($this);//重新绑定行为到组件
             $this->_behaviors[$name] = $behavior;
         }
         return $behavior;
     }

Yii源码阅读笔记(七)的更多相关文章

  1. Yii源码阅读笔记(一)

    今天开始阅读yii2的源码,想深入了解一下yii框架的工作原理,同时学习一下优秀的编码规范和风格.在此记录一下阅读中的小心得. 每个框架都有一个入口文件,首先从入口文件开始,yii2的入口文件位于we ...

  2. Yii源码阅读笔记(八)

    前面阅读了Yii2的两个基本类Object和Component,了解了Yii的三个重要概念属性.事件.行为,下面开始阅读Event类,Event类是所有事件类的基类: <?php /** * @ ...

  3. Yii源码阅读笔记(三)

    接着上次的继续阅读BaseYii.php vendor/yiisoft/yii2/BaseYii.php—— public static function getRootAlias($alias)// ...

  4. Yii源码阅读笔记(二)

    接下来阅读BaseYii.php vendor/yiisoft/yii2/BaseYii.php—— namespace yii; use yii\base\InvalidConfigExceptio ...

  5. Yii源码阅读笔记(三十五)

    Container,用于动态地创建.注入依赖单元,映射依赖关系等功能,减少了许多代码量,降低代码耦合程度,提高项目的可维护性. namespace yii\di; use ReflectionClas ...

  6. Yii源码阅读笔记(三十四)

    Instance类, 表示依赖注入容器或服务定位器中对某一个对象的引用 namespace yii\di; use Yii; use yii\base\InvalidConfigException; ...

  7. Yii源码阅读笔记(三十三)

    ServiceLocator,服务定位类,用于yii2中的依赖注入,通过以ID为索引的方式缓存服务或则组件的实例来定位服务或者组件: namespace yii\di; use Yii; use Cl ...

  8. Yii源码阅读笔记(三十二)

    web/Application类的注释,继承base/Application类,针对web应用的一些处理: namespace yii\web; use Yii; use yii\base\Inval ...

  9. Yii源码阅读笔记(三十一)

    Widget类中开始,获取视图对象,获取widget ID,渲染视图,获取路径方法注释: private $_id; /** * Returns the ID of the widget. * 返回插 ...

随机推荐

  1. WPF中的画图

    1.border(边框):      <Border BorderBrush="Blue" BorderThickness="0,1,1,1" Grid. ...

  2. maven打的jars项目,log4j不会输出日志

    通过maven打完包,运行jars时,会输出警告 log4j:WARN No appenders could be found for logger (com.dlht.DataCenterSYNC. ...

  3. node基础 --概念

    非阻塞IO: node.js使用了事件轮询 setTimeout是非阻塞的: 对于像http,net等原生模块中IO部分也采用了事件轮询,其本质是: 当node接受到浏览器的http请求时,底层的TC ...

  4. ZOJ 3157 Weapon

    题目传送门 题意:就是CF round# 329 B 的升级版,要求出相交点的个数 分析:逆序数用树状数组维护,求出非逆序数,然后所有情况(n * (n - 1)) / 2减之就是逆序数个数. #in ...

  5. python IDLE 改变窗口背景颜色

    初学Python,想必大家拿来练习最多的IDE就是Python自带的IDLE了,但是默认的代码配色及语法高亮主题确实很不适应. 能不能把IDLE配置成像sublime_text那样的主题呢? 答案是当 ...

  6. A Complete Guide to the <Picture> Element

    If you’ve ever struggled building responsive websites, this post is for you. It’s part of a series o ...

  7. 响应式HTML5+CSS3 网站开发测试实践

    仅仅利用media query适配样式是远远不够的,并没有考虑触屏下的行为和特有的内容组织方式的不同.简单在桌面版基础上叠加mobile版的代码,会带来请求增多.流量.性能.代码冗余等诸多方面问题.有 ...

  8. 洛谷 P1541 乌龟棋 Label:O(n^4)的dp

    题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...

  9. 转:10条建议让你创建更好的jQuery插件

    在开发过很多 jQuery 插件以后,我慢慢的摸索出了一套开发jQuery插件比较标准的结构和模式.这样我就可以 copy & paste 大部分的代码结构,只要专注最主要的逻辑代码就行了.使 ...

  10. 【BZOJ】1069: [SCOI2007]最大土地面积(凸包+旋转卡壳)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1069 显然这四个点在凸包上,然后枚举两个点找上下最大的三角形即可. 找三角形表示只想到三分QAQ.. ...