分享个有用的widget 用于视图上 思路来自bigpipe

小部件 · yiqing · 于 3年前 发布 · 2084 次阅读

BigPipe 是facebook 早期发明的用于加快页面加载的一种web端技术。

具体细节可以搜索下。

其基本思路是页面渲染时先渲染出 页面中各个模块的框架

	<div>
		<div id="header"> </div>
		<div id="nav">  </div>
		<div id="content"> </div>
		<div id="bottom">  </div>
	</div>

比如 页面先输出这样的框架 后续输出 为js内容 用后续输出的东西替换掉前面输出的区块, 因为使用了 并发生成内容的方式 后续区块内容输出顺序是不确定的 。 但这整个页面的生成时间 由传统的顺序准备,变为并行生成 大大缩短了页面加载时间。

简单的例子如:

	
	<div id='test'></div>

<script type="text/javascript">
 
    function render(data){
        document.getElementById(data.id).innerHTML = data.html;
    }

    render({id:"test","html":"hiiiiii"});
</script>

这样 浏览器持续加载不同的 js代码块 哪个内容先准备好 就先在哪个区块输出内容 。

比如:

	
	<script>
	 render({id:"nav",'html':"some long content  "});
	</script>
	
	<script>
	 render({id:"bottom",'html':"耗费很长时间的 内容 "});
	</script>
	
	....

在服务端 就是这样不断输出这样的 字符串。(因为是并发输出的 所以出现顺序是不确定的)

在php中 可能要借助CURL 库来并发任务

这里分享一个我搜到的 可用于完成bigpipe的库:


	var Yun_Bigpipe = function() {
    var _self = this;
    
    var js_list = {};

    this.css_handler = function(css_url_array) {
        for (i=0; i< css_url_array.length; i++) {
            jQuery("head").append("<link href='"+css_url_array[i]+"' rel='stylesheet' type='text/css' />");
        }
    }

    this.js_handler = function(js_url_array) {
         for (i=0; i< js_url_array.length; i++) {
            jQuery("head").append("<script language='javascript' src='"+js_url_array[i]+"'></script>");
        }
    }

    this.html_handler = function(id, html) {
        jQuery('#'+id).html(html);
    }
    
    this.onPageletArrive = function(data) {
        if (!('id' in data) || !('is_last' in data)) {
            return;
        }

        var id = data.id;
        if ('html' in data) {
            _self.html_handler(id, data.html);
        }

        if ('css_url' in data) {
            _self.css_handler(data.css_url);
        }

        if ('js_url' in data) {
            _self.js_handler(data.js_url);
        }

        if (data.is_last) {
            //加载javascript
        }
    }

    return this;
}();

php 端的库地址:Yun_Curl_Multi

至此 大概介绍完 bigpipe了 详细技术自行搜索吧


下来分享一个基于此思路开发的简单widget


			<?php
		/**
		 * User: yiqing
		 * Date: 2014/12/9
		 * Time: 19:54
		 */

		namespace year\widgets;


		use yii\base\Widget;

		/**
		 * 此区域中的内容会用来填充/替换指定的目标id区域
		 *
		 * Class PageletBlock
		 * @package app\widgets
		 */
		class PageletBlock extends Widget{

			/**
			 * 要被替换的div id
			 *
			 * @var string
			 */
			public $targetId = '';
			/**
			 * TODO call parent::init
			 *
			 * Starts recording a block.
			 */
			public function init()
			{
				ob_start();
				ob_implicit_flush(false);
			}

			/**
			 * Ends recording a block.
			 * This method stops output buffering and saves the rendering result as a named block in the view.
			 */
			public function run()
			{
				$block = ob_get_clean();

				$id = $this->getId();
				$content = [];

				$content[] = <<<EOD
			<script id="{$id}" type="text/x-my-template">
			   {$block}
			</script>
		EOD;
			  $content[] = <<<JS_REPLACE
			<script  type="text/javascript">
			   document.getElementById("{$this->targetId}").innerHTML =
					document.getElementById("{$id}").innerHTML ;
			</script>
		JS_REPLACE;
			  return implode("\n",$content) ;

			}
		} 
	

使用方法, 比如 在表单中 使用了ActiveForm 对于有些复杂界面 为了不破坏yii自带的实现 可以使用上面的小组件


	<?php echo $form->field($model, 'goods_id',[
            'template'=>"<td>{label}</td>\n<td>{input}</td>\n<td>{error}<span id='goods_selection'></span></td>",
    ])->textInput([
            'class'=>'easyui-textbox goods-id',
        'data'=>[
                'options'=>'readonly:true',
        ]
    ]) ?>

    <?php  \year\widgets\PageletBlock::begin([
            'targetId'=>'goods_selection'
    ]) ?>
        <a href='javascript:void(0)' onclick="purchaseRequisitionItemForm.selectGoods(this)">请选择商品</a>
    <?php \year\widgets\PageletBlock::end() ?>

下面这个例子 是用在 GridView 布局中 用此技术 你几乎可以随意定制它的布局 在某个位置输出大段html代码

如果不用此技术 你需要用字符串拼出html字符串 这会导致代码相当难看

	
	   <?= GridView::widget([
        'id' => 'msg-grid',
        'layout' => "  <div id='pl_grid_tools_bar'></div> {pager} \n {items}\n{summary}  \n {pager} ",
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
           // ['class' => 'yii\grid\SerialColumn'],
              ['class' => \yii\grid\CheckboxColumn::className()],

            'id',
            'type',
            'uid',
            'data:ntext',
            'snd_type',
            // 'snd_status',
            // 'priority',
            // 'to_id',
            // 'msg_pid',
            // 'create_time:datetime',
            // 'sent_time:datetime',
            // 'delete_time:datetime',

            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>
	
	 <?php  \year\widgets\PageletBlock::begin(['targetId'=>'pl_grid_tools_bar']) ?>

<div class="panel panel-default">
    <div class="panel-body">
        <a class="btn">
            <input type="checkbox"  name="selection_all" class="select-on-check-all copy">
        </a>
                <div class="btn-group batch-action-buttons" role="group" aria-label="..." >
               <?=  Html::submitButton( 'DELETE',[
                'name'=>'batchDelete' ,
                'class'=>'batch-action-button btn btn-danger btn-sm' , // btn-xs
                'data'=>[
                    'action'=>'batch-delete',
                    'confirm-message'=>'do you want to perform this action ?',
                ]
            ]) ?>
               <?=  Html::submitButton('UPDATE',[
                'name'=>'batchUpdate' ,
                'class'=>'batch-action-button btn btn-info btn-sm' , // btn-xs
                'data'=>[
                    'action'=>\yii\helpers\Url::to(['batch-update'])
                ]
            ]) ?>
        </div>
    </div>
</div>
   <?php  \year\widgets\PageletBlock::end() ?>

本文由 yiqing 创作,采用 知识共享署名 3.0 中国大陆许可协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。

本帖已被设为精华帖!
共收到 0 条回复 Yii2模块
没有找到数据。
添加回复 (需要登录)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册