Alexander Makarov
10 years ago
1 changed files with 201 additions and 0 deletions
@ -0,0 +1,201 @@
|
||||
Виджеты |
||||
======= |
||||
|
||||
Виджеты представляют собой многоразовые строительные блоки, используемые в [представлениях](structure-views.md) |
||||
для создания сложных и настраиваемых элементов пользовательского интерфейса в рамках объектно-ориентированного |
||||
подхода. Например, виджет выбора даты (date picker) позволяет генерировать интерактивный интерфейс для выбора дат, |
||||
предоставляя пользователям приложения удобный способ для ввода данных такого типа. Все, что нужно для |
||||
подключения виджета - это добавить следующий код в представление: |
||||
|
||||
```php |
||||
<?php |
||||
use yii\bootstrap\DatePicker; |
||||
?> |
||||
<?= DatePicker::widget(['name' => 'date']) ?> |
||||
``` |
||||
|
||||
В комплект Yii входит большое количество виджетов, например: [[yii\widgets\ActiveForm|active form]], |
||||
[[yii\widgets\Menu|menu]], [виджеты jQuery UI](widget-jui.md), [виджеты Twitter Bootstrap](widget-bootstrap.md). |
||||
Далее будут представлены базовые сведения о виджетах. Для получения сведений относительно использования |
||||
конкретного виджета, следует обратиться к документации соответствующего класса. |
||||
|
||||
|
||||
## Использование Виджетов <a name="using-widgets"></a> |
||||
|
||||
Главным образом, виджеты применяют в [представлениях](structure-views.md). Для того, чтобы использовать виджет |
||||
в представлении, достаточно вызвать метод [[yii\base\Widget::widget()]]. Метод принимает массив [настроек](concept-configurations.md) |
||||
для инициализации виджета и возвращает результат его рендеринга. Например, следующий |
||||
код добавляет виджет для выбора даты, сконфигурированный для использования русского в качестве языка интерфейса |
||||
виджета и хранения вводимых данных в атрибуте `from_date` модели `$model`. |
||||
|
||||
```php |
||||
<?php |
||||
use yii\bootstrap\DatePicker; |
||||
?> |
||||
<?= DatePicker::widget([ |
||||
'model' => $model, |
||||
'attribute' => 'from_date', |
||||
'language' => 'ru', |
||||
'clientOptions' => [ |
||||
'dateFormat' => 'yy-mm-dd', |
||||
], |
||||
]) ?> |
||||
``` |
||||
|
||||
Некоторые виджеты могут иметь внутреннее содержимое, которое следует располагать между вызовами методов |
||||
[[yii\base\Widget::begin()]] и [[yii\base\Widget::end()]]. Например, для генерации формы входа, в следующем |
||||
фрагменте кода используется виджет [[yii\widgets\ActiveForm]]. Этот виджет сгенерирует открывающий и закрывающий |
||||
тэги `<form>` в местах вызова методов `begin()` и `end()` соответственно. При этом, содержимое, расположенное |
||||
между вызовами указанных методов будет выведено без каких-либо изменений. |
||||
|
||||
```php |
||||
<?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()]] возвращает экземпляр виджета, который может быть |
||||
использован в дальнейшем для формирования его внутреннего содержимого. |
||||
|
||||
|
||||
## Создание Виджетов <a name="creating-widgets"></a> |
||||
|
||||
Для того, чтобы создать виджет, следует унаследовать класс [[yii\base\Widget]] и переопределить методы |
||||
[[yii\base\Widget::init()]] и/или [[yii\base\Widget::run()]]. Как правило, метод `init()` должен содержать |
||||
код, выполняющий нормализацию свойств виджета, а метод `run()` - код, возвращающий результат рендеринга виджета. |
||||
Результат рендеринга может быть выведен непосредственно с помощью конструкции "echo" или же возвращен |
||||
в строке методом `run()`. |
||||
|
||||
В следующем примере, виджет `HelloWidget` HTML-кодирует и отображает содержимое, присвоенное свойству `message`. |
||||
В случае, если указанное свойство не установлено, виджет, в качестве значения по умолчанию отобразит строку "Hello World". |
||||
|
||||
```php |
||||
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 |
||||
<?php |
||||
use app\components\HelloWidget; |
||||
?> |
||||
<?= HelloWidget::widget(['message' => 'Good morning']) ?> |
||||
``` |
||||
|
||||
Ниже представлен вариант виджета `HelloWidget`, который принимает содержимое, обрамленное вызовами методов |
||||
`begin()` и `end()`, HTML-кодирует его и выводит. |
||||
|
||||
```php |
||||
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); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Как Вы можете видеть, в методе `init()` происходит включение буферизации вывода PHP таким образом, что весь вывод |
||||
между вызовами `init()` и `run()` может быть перехвачен, обработан и возвращен в `run()`. |
||||
|
||||
> Информация: При вызове метода [[yii\base\Widget::begin()]] будет создан новый экземпляр виджета, при этом |
||||
вызов метода `init()` произойдет сразу после выполнения остального кода в конструкторе виджета. |
||||
При вызове метода [[yii\base\Widget::end()]], будет вызван метод `run()`, а возвращенное им значение будет выведено |
||||
методом `end()`. |
||||
|
||||
Следующий фрагмент кода содержит пример использования модифицированного варианта `HelloWidget`: |
||||
|
||||
```php |
||||
<?php |
||||
use app\components\HelloWidget; |
||||
?> |
||||
<?php HelloWidget::begin(); ?> |
||||
|
||||
content that may contain <tag>'s |
||||
|
||||
<?php HelloWidget::end(); ?> |
||||
``` |
||||
|
||||
В некоторых случаях, виджету может потребоваться вывести крупный блок содержимого. И хотя это содержимое может |
||||
быть встроено непосредственно в метод `run()`, целесообразней поместить его в [представление](structure-views.md) |
||||
и вызвать метод [[yii\base\Widget::render()]] для его рендеринга. Например, |
||||
|
||||
```php |
||||
public function run() |
||||
{ |
||||
return $this->render('hello'); |
||||
} |
||||
``` |
||||
|
||||
По умолчанию, файлы представлений виджетов должны находиться в директории `WidgetPath/views`, где `WidgetPath` - |
||||
директория, содержащая файл класса виджета. Таким образом, в приведенном выше примере, для виджета будет |
||||
использован файл представления `@app/components/views/hello.php`, при этом файл с классом виджета расположен в |
||||
`@app/components`. Для того, что бы изменить директорию, в которой содержатся файлы-представления для виджета, |
||||
следует переопределить метод [[yii\base\Widget::getViewPath()]]. |
||||
|
||||
|
||||
## Лучшие Практики <a name="best-practices"></a> |
||||
|
||||
Виджеты представляют собой объектно-ориентированный подход к повторному использованию кода пользовательского |
||||
интерфейса. |
||||
|
||||
При создании виджетов, следует придерживаться основных принципов концепции MVC. В общем случае, основную логику |
||||
следует располагать в классе виджета, разделяя при этом код, отвечающий за разметку в [представления](structure-views.md). |
||||
|
||||
Разрабатываемые виджеты должны быть самодостаточными. Это означает, что для их использования должно быть |
||||
достаточно всего лишь добавить виджет в представление. Добиться этого бывает затруднительно в том случае, |
||||
когда для его функционирования требуются внешние ресурсы, такие как CSS, JavaScript, изображения и т.д. |
||||
К счастью, Yii предоставляет поддержку механизма для работы с ресурсами [asset bundles](structure-asset-bundles.md), |
||||
который может быть успешно использован для решения данной проблемы. |
||||
|
||||
В случае, когда виджет не содержит логики, а содержит только код, отвечающий за вывод разметки, он мало |
||||
отличается от [представления](structure-views.md). В действительности, единственное его отличие состоит в том, что |
||||
виджет представляет собой отдельный и удобный для распространения класс, в то время как представление - это |
||||
обычный PHP скрипт, подходящий для использования только лишь в конретном приложении. |
Loading…
Reference in new issue