View on GitHub

yii2-cookbook-chinese

Yii Application Development Cookbook(Third Edition)中文翻译

Pjax JQuery插件

Pjax是一个小组件,它集成了pjax jQuery插件。所有被这个小组件包括的内容,可以通过AJAX加载,而不需要刷新当前页面,这个小组件在你浏览器的地址栏中也使用HTML5 History API来修改当前URL。

准备

按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。

如何做…

在下面的例子中,你可以看到如何通过yii\grid\GridView小组件来使用Pjax:

<?php
use yii\widgets\Pjax;
?>
<?php Pjax::begin(); ?>
    <?= GridView::widget([...]); ?>
<?php Pjax::end(); ?>

只需要在Pjax::begin()Pjax::end()包裹任何代码片段。

这将会渲染出如下HTML代码:

<div id="w1">
    <div id="w2" class="grid-view">...</div>
</div>
<script type="text/javascript">jQuery(document).ready(function () {
    jQuery(document).pjax("#w1 a", "#w1", {...});
});</script>

所有被包裹的内容,包括翻页和排序链接,都会通过AJAX重新加载。

指定一个自定义ID

Pjax从AJAX请求获取页面内容,然后使用相同的ID释放它自己的DOM元素。你可以通过渲染没有布局的内容加速页面渲染性能,尤其是对于Pjax请求:

public function actionIndex()
{
    $dataProvider = ...;
    if (Yii::$app->request->isPjax) {
        return $this->renderPartial('_items', [
            'dataProvider' => $dataProvider,
        ]);
    } else {
        return $this->render('index', [
            'dataProvider' => $dataProvider,
        ]);
    }
}

默认情况下,yii\base\Widget::getId方法会自增标识符,因此小组件在任何页面上,都会有一个自增的属性:

<nav id="w0">...</nav> // Main navigation
<ul id="w1">...</ul> // Breadcrumbs widget
<div id="w2">...</div> // Pjax widget

使用renderPartial()或者renderAjax()方法进行渲染,不需要渲染布局,你自己的页面将会有一个带有数字0的小组件:

<div id="w0">...</div> // Pjax widget

在这个结果中,你自己的小组件将不会在下次请求中通过w2选择器找到自己的block。

但是,Pjax将会在Ajax响应中通过w2选择器找到相同的block。在这个结果中,你自己的小组件将不会在下次请求中通过w2选择器找到这个block。

因此,你必须为你的Pjax小组件手动指定一个唯一标识符,来避免冲突:

<?php Pjax::begin(['id' => 'countries']) ?>
    <?= GridView::widget([...]); ?>
<?php Pjax::end() ?>

使用ActiveForm

默认情况下,Pjax只和被包裹的快交互。如果你想和ActiveForm小组件一起使用它,你必须使用表单的data-pjax选项:

<?php
use \yii\widgets\Pjax
use \yii\widgets\ActiveForm;
<?php yii\widgets\Pjax::begin(['id' => 'my-block']) ?>
<?php $form = ActiveForm::begin(['options' => [
    'data-pjax' => true,
]]); ?>
<?= $form->field($model, 'name') ?>
<?php ActiveForm::end(); ?>
<?php Pjax::end(); ?>

它会为表单的提交事件添加相应的监听器。

你也可以使用Pjax小组件的$formSelector选项,来指定什么表单提交将会出发pjax

使用客户端脚本

你可以订阅容器事件:

<?php $this->registerJs('
    $("#my-block").on("pjax:complete", function() {
        alert('Pjax is completed');
    });
'); ?>

或者,你可以通过使用它的选择器,手动重新加载容器:

<?php $this->registerJs('
    $("#my-button").on("click", function() {
        $.pjax.reload({container:"#my-block"});
    });
'); ?>

工作原理…

Pjax是任何代表片段的一个容器。它订阅片段中所有链接的点击事件,并替换整个页面,使用Ajax调用重新加载它。我们可以使用data-pjax属性用于被包裹的表单,以及任何表单提交将会触发一个Ajax请求。

这个小组件将会加载和更新on-the-fly小组件内容,而不需要再加布局资源(JS,CSS)。

你可以配置小组件的$linkSelector来指定什么链接将会触发Pjax,以及配置$formSelector来指定什么样的表单提交将会触发Pjax。

你可以为容器中一个指定的链接禁用Pjax,方法是给这个链接添加一个data-pjax="0"属性。

参考