• 渲染方法yii框架页面渲染


    之前一直在研究渲染方法之类的问题,上午正好有机会和大家讨论一下.

        

    1、一般页面渲染

        yii的页面渲染通过在controller的action中调用$this->render($viewname...)进行,流程如下图:渲染和方法

        在render方法中,yii会先对你的view文件进行渲染,然后如果你使用了某些layouts,则会将view渲染的输出再传入对layouts的渲染方法中,上述这两步在虚线框中表现了,简单的页面渲染就是这样的。

        当然这里面有些技能需要注意,首先是黑框中显示的那几行代码(位于renderInternal方法中),yii首先启用输出缓冲,并制止隐式的冲掉缓冲,然后require需要渲染的视图文件,最后再获得缓冲区的全部内容,即最终的渲染结果。这样处理有3个利益:

        1.视图文件中多次echo也必须最后一同输出;

        2.可以在视图文件中使用$this,即当前的controller对象。

        3.第三个利益是这样的,黑框中漏掉了一句“extract($_data_,EXTR_PREFIX_SAME,'data');”,extract函数的作用是将$_data_数组中的$key=>$value对酿成当前作用域中的$key = $value赋值,这样视图文件中就可以直接使用$key引用$value的值了。不知道smarty中变量赋值是怎么进行的,但是感觉yii这类方式高效很多,因为不再需要使用php实现词法分析之类的功能了。

        这个技能我们可以自己简单实现一下,就会明白它的原理了。编写代码如下:

    class Controller
    {
        private $name='';
    
        public function __construct($name)
        {   
            $this->name = $name;
        }   
    
        public function render($viewName, $data)
        {   
            extract($data, EXTR_PREFIX_SAME,'data');
            ob_start();
            ob_implicit_flush(0);
    
            require($viewName . '.php');
            echo ob_get_clean();
        }   
    }
    
    $ctrl = new Controller('php');
    $ctrl->render('view', array('age'=>20));  //模拟render方法调用
    echo $this->name . "\n" . $age . "\n";    //view.php只有一句

        假设第一段代码存为controller.php,第二段存为view.php(若存为其他名字,请相应修改调用render时传入的名字),在终端执行php controller.php会输出:

    php
    20

        原来view.php中是没有$this和$age的,但是因为require时给予了它render方法的作用域,并且采取了extract方法操纵传入的数组参数,使得读取这两个变量成为可能。

        

    2、嵌套了layout的视图文件的渲染

        这里嵌套是指controller采取了layout1并渲染视图view,而layout1又采取了布局layout2。采取layout1并渲染view是上

        一部分的内容,而在layout1中采取layout2是这部分要讲的。采取这类方式进行渲染,通常需要在layout1中调用

        每日一道理
    翻开早已发黄的页张,试着寻找过去所留下的点点滴滴的足迹。多年前的好友似乎现在看来已变得陌生,匆忙之间,让这维持了多年的友谊变淡,找不出什么亲切感,只是偶尔遇上,淡淡地微笑,如今也只能在这发黄的页张中找寻过去的那些让人难忘的,至少我可以握住这仅剩下一段的“丝线头”……

        controller的beginContent(layout2)方法,并传入layout2的名称,然后在渲染结束后再调用controller的endContent()

        方法结束渲染进程。伪码如下:

        

    <?php
    // $this is the controller
    $this->beginContent('layout2');
    ?>
    some html and/or <?php echo $content; ?>
    <?php $this->endContent(); ?>

        这里就要讲这两个方法以及整个进程的实现机制。先来看beginContent的任务流程:

        渲染和方法

        请注意这一连串的进程都是在当前controller的作用域进行的。可以看到beginContent调用beginWidget并传入了一个

        类名,这个类的实例就是前面的widget,表现了一个装饰器,注意在createWidget时传入了当前controller的实例,并

        且会对widget的view属性赋值为layout名称(这里的进程还要稍微庞杂些,但是大致的意图是这样的,具体可参考源

        码),这两个变量前面有效;然后调用widget的Init方法使其初始化,并将其缓存到controller的一个stack中。值得注

        意的是init方法里做了什么:很熟悉,打开了输出缓冲区。用处是什么,看了第一部分你应当懂~~下面再看

        endContent的执行进程:

        渲染和方法

        这个进程稍微庞杂些,先说明一直到第一个虚线框(包含)都是在当前controller的作用域,以后都是在widget的作用

        域了。可以看到调用endContent以后其实先从controller的那个stack中弹出了先前保存的widget,然后调用widget的

        run方法。以后就主要是widget的任务了,首先是熟悉的ob_get_clean()拿到缓冲区中的内容,参考伪码你会明白,

        此时缓冲区中的内容是“some html and/or ...”,即你写的页面html和要echo出的货色;然后重要的任务在decorate方

        法中,它会通知controller去获得layout文件,并通知controller渲染这个文件,但是controller在哪儿?就是widget的

        owner属性,表现谁拥有这个widget,还记得在beginContent中向widget实例传入了controller对象吧?:) 以后的进程

        就简单了,跟渲染普通视图文件一样,只不过这里会将从缓冲区失掉的内容全部传给视图文件,并获得最终的渲染结

        果。

        同样的,我们也可以写个demo模拟这个渲染进程,编写代码如下:

        

    <?php
    class Decorator
    {
        public function begin()
        {
            ob_start();
            ob_implicit_flush(0);
        }   
        
        public function decorate($content)
        {
            echo 'from Decorator ' . $content;
        }   
        
        public function end()
        {
            $output = ob_get_clean();
            $this->decorate($output);
        }   
    }   
    ?>
    require_once('dec.php');
    $dec = new Decorator();
    $dec->begin();
    ?>
    
    <h1>sddfds</h1>
    <?php echo 'hello'; ?>
    
    <?php $dec->end(); ?>

        假设第一段代码为dec.php表现装饰器,第二段为layout.php,表现布局文件,运行php layout.php应当会输出:

        

    from Decorator 
    <h1>sddfds</h1>
    hello

        这个简化的进程能便利懂得框架里的渲染流程。

        

    3、总结

        yii的两种渲染进程都有效的利用了语言的输出缓冲,而第二种方式更是通过将“开缓冲”和“取缓冲”的操纵分分开,

        进而实现了对这两个操纵之间的输出内容进行装饰的功能。

    文章结束给大家分享下程序员的一些笑话语录: 自从有了Photoshop,我再也不相信照片了!(没有Photoshop的年代,胶片照片年代做假的也不少,那时候都相信假的!)

    --------------------------------- 原创文章 By
    渲染和方法
    ---------------------------------

  • 相关阅读:
    异步编程系列第04章 编写Async方法
    异步编程系列第03章 自己写异步代码
    异步编程系列第02章 你有什么理由使用Async异步编程
    异步编程系列第01章 Async异步编程简介
    初探asp.net异步编程之await
    Sql Server 覆盖索引
    把cookie以json形式返回,用js来set cookie.(解决手机浏览器未知情况下获取不到cookie)
    redis+cookies实现session机制(解决 手机浏览器不自动回传cookies导致session不可用问题)
    把阅读当作一种人生习惯来培养
    SAS中的剔除空格函数
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3100512.html
Copyright © 2020-2023  润新知