阿江 2017-10-08 17:11:15 2693次浏览 0条回复 0 0 0

说明

学习Yii Framework 2易2框架的过程是漫长的也是充满乐趣的以下是我学习Yii2框架时对官网英文资料(请参见原文网址)的翻译和代码实现提供了较完整的代码供你参考不妥之处请多多指正

原文网址:

http://www.yiiframework.com/doc-2.0/guide-structure-widgets.html

本文主题:小部件(Widgets)

小部件是可重用的构建块,使用面向对象风格在视图中创建复杂的、可配置的用户界面。例如,一个日期选择小部件可以创建一个漂亮的日期选择器,允许用户选取时间,如同他们自己输入的一样。需要你做的只是在视图中插入以下代码:

<?php
use yii\jui\DatePicker;
?>
<?=DatePicker::widget(['name'=>'date'])?>

与Yii绑定的小部件有很多,如active form,menu,JQuery UI widgets,Twitter Bootstrap widgets。接下来,我们将介绍小部件的基础知识。如果你想要知道某个小部件的用法请参考类API文件。

1、Using Widgets(使用小部件)

小部件主要在视图中使用。你可以在视图中调用yii\base\Widget::widget()方法来使用一个小部件。此方法使用一个配置数组来初始化小部件,返回小部件的渲染结果。例如,以下代码插入一个日期选择器小部件,它配置使用俄语,并将输入保存在$model 的form_date属性中。

<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget([
    'model' => $model,
    'attribute' => 'from_date',
    'language' => 'ru',
    'dateFormat' => 'php:Y-m-d',
]) ?>

一些小部件可以获取块内容,即调用yii\base\Widget::begin()和yii\base\Widget::end()方法封装起来的块内容。例如,以下代码使用yii\widgets\ActiveForm小部件生成一个登录表单。这个小部件将在调用begin()和end()方法的地方分别生成

开合标签。两个标签之间的内容都会被渲染为合适的元素。
<?php
use yii\widgets\ActiveForm;
use yii\helpers\Html;
?>
<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>
    <?= $form->field($model, 'username') ?>
    <?= $form->field($model, 'password')->passwordInput() ?>
    <div class="form-group">
        <?= Html::submitButton('Login') ?>
    </div>
<?php ActiveForm::end(); ?>

注意,与yii\base\Widget::widget()返回渲染结果不同的是,yii\base\Widget::begin()返回一个小部件的实例,使用它可以构建小部件的内容。

注意:当yii\base\Widget::end()被调用时,一些小部件使用输出缓存来调整闭合区的内容。正因如此,yii\base\Widget::begin()和yii\base\Widget::end()需要在同一个视图文件中成对出现。不遵守此条规则可能会导致不正确的输出。

Configuring global defaults(配置全局默认值)

通过DI容器可以配置小部件的全局默认值:

\Yii::$container->set('yii\widgets\LinPager',['maxButtonCount'=>5]);

详情请查看: Dependency Injection Container的Practical Usage章节: http://www.yiiframework.com/doc-2.0/guide-concept-di-container.html#practical-usage

2、Creating Widgets

要创建一个小部件,需要从yii\base\Widget中继承,并重写yii\base\Widget::init()和yii\base\Widget::run()方法。通常init()方法初始化小部件的属性,run()方法将包含生成小部件渲染结果的代码。渲染结果可以被直接显示出来,也可以由run()方法返回一个字符串。

在下例中,HelloWidget将message属性中的内容进行HTML编码并显示出来。如果此属性没有被设置,它将显示"Hello World":

namespace app\components;
use yii\base\Widget;
use yii\helpers\Html;
class  HelloWidget extends Widget{
	public $message;
	public function init(){
		parent::init();
		if($this->message===null){
			$this->message='Hello World';
		}
	}
	public function run(){
		return Html::encode($this->message);
	}
}

要使用这个小部件,只需将以下代码插入到视图中即可:

<?php
use app\components\HelloWidget;	
?>
<?=HelloWidget::widget(['message'=>'Good morning'])?>

下例与HelloWidget不同,它获取begin()和end()闭合区间的内容,进行HTML编码然后显示出来。 D:\phpwork\news\components\BlockWidget.php

namespace app\components;
use yii\base\Widget;
use yii\helpers\Html;
class  BlockWidget extends Widget{
    public $message;
    public function init(){
        parent::init();
        ob_start();
    }
    public function run(){
        $content=ob_get_clean();
        return Html::encode($content);
    }
}

正如你看到的,PHP的输出缓存在init()中开启,这样init()与run()方法之间的任何输出都可以被捕获,在run()中处理后返回。 信息:当你调用yii\base\Widget::begin()时,小部件的一个新实例将被创建,init()方法将在小部件构造器的末尾被调用。当你调用yii\base\Widget::end()时,run()方法将被调用,它将返回end()要显示的内容。

以下代码展示了如何使用BlockWidget: D:\phpwork\news\modules\admin\views\default\index.php

<?php
use app\components\BlockWidget;
?>
    <?php
    BlockWidget::begin();
    ?>
    <p>
        This is the view content for action "<?= $this->context->action->id ?>".
        The action belongs to the controller "<?= get_class($this->context) ?>"
        in the "<?= $this->context->module->id ?>" module.
    </p>
    <?php
    BlockWidget::end();
    ?>
测试结果:
http://localhost:8085/admin
/*
<p> This is the view content for action "index". The action belongs to the controller "app\modules\admin\controllers\DefaultController" in the "admin" module. </p>
*/

有时,一个小部件可能需要渲染大量内容,虽然你也可以将这些内容放置在run()方法内,但更好的办法是将它们放到一个视图文件中,然后调用yii\base\Widget::render()方法来渲染它,例如:

public function run(){
	return $this->render('hello');
}

默认情况下,小部件的视图会存储在WidgetPath/views目录下,WidgetPath表示包含小部件类文件的目录。因此,假设小部件类位于@app/components目录,上例将渲染视图文件@app/components/views/hello.php。你可以重写yii\base\Widget::getViewPath()方法来自定义包含小部件视图文件的目录。

D:\phpwork\news\components\RenderWidget.php

<?php
namespace app\components;
use yii\base\Widget;
class RenderWidget extends Widget{
    public function init(){
        parent::init();
    }
    public function run(){
        return $this->render('render');
    }
}

D:\phpwork\news\modules\admin\views\default\index.php

<?php
use app\components\RenderWidget;
?>
    <?=RenderWidget::widget();?>

D:\phpwork\news\components\views\render.php

this is render file!
#### 测试结果:

http://localhost:8085/admin / this is render file! /


### 3、Best Practices(最佳实践)
小部件是使用面向对象的方法来复用视图代码当创建小部件时,你仍然需要遵循MVC模式,通常情况下,你应将逻辑代码放在小部件类文件中,将显示内容放在视图中。
小部件应被设计为自包含,也就是说,当使用一个小部件时,你只需将它放到一个视图中而无需做其他事情。如果一个小部件需要外部资源,如CSS、JavaScript、图片等,它将变得很复杂。庆幸的是,Yii提供了资源集(asset bundles)支持,可以使用它来解决这个问题。
当一个小部件只包含视图代码时,它与视图就非常相似了。实际上,在这种情况下,它们的唯一区别是小部件是一个可再分发的类,而视图则是一个只在你的应用中使用的PHP脚本文件。

## (全文完)
    没有找到数据。
您需要登录后才可以回复。登录 | 立即注册