[Yii2笔记]041小部件(Widgets) [ 技术分享 ]
说明
学习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脚本文件。
## (全文完)
共 0 条回复
阿江
最后登录:2024-03-03
在线时长:186小时21分
- 粉丝94
- 金钱16816
- 威望160
- 积分20276