小部件是在 视图 中使用的可重用构建块,用于以面向对象的方式创建复杂且可配置的用户界面元素。例如,日期选择器小部件可能会生成一个花哨的日期选择器,允许用户选择一个日期作为输入。您只需要在视图中插入以下代码即可
<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget(['name' => 'date']) ?>
Yii 附带了大量小部件,例如 活动表单、菜单、jQuery UI 小部件、Twitter Bootstrap 小部件。在下文中,我们将介绍关于小部件的基本知识。如果您想了解特定小部件的使用方法,请参考类 API 文档。
小部件主要用于 视图 中。您可以调用 yii\base\Widget::widget() 方法在视图中使用小部件。该方法接收一个用于初始化小部件的 配置 数组,并返回小部件的渲染结果。例如,以下代码插入了一个日期选择器小部件,该小部件被配置为使用俄语并保留输入在 $model
的 from_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()
的地方生成 <form>
的开始和结束标签。两者之间的任何内容都将按原样呈现。
<?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()。不遵循此规则可能会导致意外输出。
可以通过 DI 容器配置小部件类型的全局默认值
\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);
有关详细信息,请参阅 "依赖注入容器指南中的实际使用部分"。
根据需求,小部件可以通过两种不同的方式创建。
要创建小部件,请继承自 yii\base\Widget 并重写 yii\base\Widget::init() 和/或 yii\base\Widget::run() 方法。通常,`init()` 方法应该包含初始化小部件属性的代码,而 `run()` 方法应该包含生成小部件渲染结果的代码。渲染结果可以通过 `run()` 直接 "echo" 或者作为字符串返回。
在以下示例中,`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']) ?>
有时,小部件可能需要渲染大量内容。虽然可以在 `run()` 方法中嵌入内容,但更好的方法是将其放入 视图 中,并调用 yii\base\Widget::render() 来渲染它。例如:
public function run()
{
return $this->render('hello');
}
这与上面类似,但略有不同。下面是 `HelloWidget` 的一个变体,它接收 `begin()` 和 `end()` 调用之间包含的内容,对其进行 HTML 编码,然后显示它。
namespace app\components;
use yii\base\Widget;
use yii\helpers\Html;
class HelloWidget extends Widget
{
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()` 输出。
以下代码展示了如何使用这个 `HelloWidget` 的新变体:
<?php
use app\components\HelloWidget;
?>
<?php HelloWidget::begin(); ?>
sample content that may contain one or more <strong>HTML</strong> <pre>tags</pre>
If this content grows too big, use sub views
For e.g.
<?php echo $this->render('viewfile'); // Note: here render() method is of class \yii\base\View as this part of code is within view file and not in Widget class file ?>
<?php HelloWidget::end(); ?>
默认情况下,小部件的视图应存储在 `WidgetPath/views` 目录中的文件中,其中 `WidgetPath` 代表包含小部件类文件的目录。因此,上面的示例将渲染视图文件 `@app/components/views/hello.php`,假设小部件类位于 `@app/components` 下。您可以覆盖 yii\base\Widget::getViewPath() 方法来自定义包含小部件视图文件的目录。
小部件是重用视图代码的面向对象方式。
创建小部件时,您应该遵循 MVC 模式。一般来说,您应该将逻辑保留在小部件类中,并将演示保留在 视图 中。
小部件的设计应该自包含。也就是说,当使用小部件时,您应该能够将其直接放入视图中,而无需做任何其他事情。如果小部件需要外部资源(如 CSS、JavaScript、图像等),这可能会很棘手。幸运的是,Yii 提供了对 资产包 的支持,可以用来解决这个问题。
当小部件仅包含视图代码时,它与 视图 非常相似。实际上,在这种情况下,它们唯一的区别是,小部件是可重新分发的类,而视图只是一个普通的 PHP 脚本,您可能希望将其保留在应用程序中。
发现错字或您认为此页面需要改进?
在 GitHub 上编辑它 !
注册 或 登录 以发表评论。