Pjax在Yii2中保持刷新整个页面,在listview中多次调用Pjax

时间:2015-12-28 21:26:32

标签: yii2 yii2-advanced-app pjax

我这几天一直在努力解决这个问题,基本上我想尝试一下commetn和孩子的评论, 评论有一个名为'retrievecomment'的按钮/链接来检索子评论。

我发现pjax无法正常工作,它会让整个页面更新。

    <div class="row">   
            <?= $model['comment']?>
    </div>
    <div class="row">
        <div id="selector"align="right">
            <?= Html::a('Retrieve Comment', ["../../thread/index?id=" . $model['thread_id'] . "&comment_id=" . $comment_id], 
                                        ['data-pjax' => '#childCommentData-'.$comment_id, 'class' => 'btn btn-default'
                                        ,'id' => 'retrieveComment' . $comment_id]) ?>
        </div>

        <?php Pjax::begin([
            'id' => 'childCommentData-'.$comment_id,
            'clientOptions'=>[
                    'timeout' => 5000,
                    'registerClientScript' => "$.pjax.reload({container:'#childCommentData-$comment_id'});",
                    'linkSelector'=>'#retrieveComment'.$comment_id
                    ]
            ]);?>

            <div  class="col-md-12">

                <?php if(isset($retrieveChildData)){ ?>
                    <?= ListView::widget([

                            'dataProvider' => $retrieveChildData,
                            'options' => [
                                'tag' => 'div',
                                'class' => 'list-wrapper',
                                    'id' => 'list-wrapper',
                            ],
                                'layout' => "\n{items}\n{pager}",

                            'itemView' => function ($model, $key, $index, $widget) {
                                return $this->render('_list_child_comment',['model' => $model]);
                            }, 
                            'pager' => [
                                'firstPageLabel' => 'first',
                                'lastPageLabel' => 'last',
                                'nextPageLabel' => 'next',
                                'prevPageLabel' => 'previous',
                                'maxButtonCount' => 3,
                            ],
                        ]) ?>

                <?php } ?>


            </div>
        <?php Pjax::end();?>
    </div>

</div>

在listview中多次调用注释的Pjax,我相信这已成为问题,因为编译器混淆了要重新加载的pjax,

控制器代码(在actionIndex内)

            else if(!empty($_GET['comment_id'])){
                $comment_id = $_GET['comment_id'];

                //retrieve yes data
                $retrieveChildData = new SqlDataProvider([
                    'sql' => Comment::retrieveChildComment($comment_id),  
                    'totalCount' => Comment::countChildComment($comment_id),
                    'pagination' => [
                        'pageSize' =>5,
                        ],

                ]);
                return $this->render('_list_comment.php', ['retrieveChildData' => $retrieveChildData]);

            }

1 个答案:

答案 0 :(得分:6)

最常见的问题 - 来源

通常pjax的整页刷新有两个可能的来源:

  1. 您的pjax请求超出了pjax设置中设置的超时。这导致整页刷新
  2. 在第一个pjax请求完成之前触发另一个pjax请求,这也会导致整页刷新,因为pjax不支持多个并行刷新
  3. 如何解决#1

    这个很容易,看起来你已经弄明白了。您只需要增加pjax-timeout值。您可以单独在每个窗口小部件实例上执行此操作,也可以像以下一样全局设置它:

    if ($.pjax) {
        $.pjax.defaults.timeout = 5000;
    }
    

    上面的代码将所有pjax-instances的默认超时设置为5000ms。通常绰绰有余。对于复杂的Web应用程序,通常的默认值650ms相当紧凑。

    您可以在官方网站上找到所有选项:here

    如何解决#2

    这有点棘手,看起来这是你的问题。要找到答案,请查看调试工具栏并确保保留日志页面(在Chrome中,此设置名称为preserve log在网络选项卡下。如果您看到多个请求触发,这就是您的问题!

    如果是这样,您必须先执行自己的检查,以确保在仍有一些运行时不会触发其他pjax请求。如果你不这样做,并且用户在一个接一个地快速点击两个按钮,无论如何都会遇到这个。

    我通常通过实现一个运行多少个ajax请求的计数器来阻止这种情况。如果计数器为0,则触发新请求,否则我将等待。

    ajax-counter的示例:

    //this is the actual counter
    var ajaxCounter = 0;
    
    //this method is called whenever an ajax-request fires
    $(document).ajaxSend(function() {
        ajaxCounter++;
    });
    
    //this method is called whenever an ajax-request finishes...no matter of its result
    $(document).ajaxComplete(function() {
        ajaxCounter--;
    });
    
    //check if pjax calls are allowed right now
    var pjaxAllowed = function () {
        return ajaxCounter == 0;
    }
    

    Etvoilà!在触发pjax之前,您只需检查是ajaxCounter == 0还是使用方便功能pjaxAllowed(),如上所示。如果你不想每次都检查这个,你可以实现自己的小pjax-request-stack。 pjax提供的事件非常容易实现:Pjax-Events

    我希望我可以帮助你。这个也给我带来了一些麻烦;)!如果您需要更多信息,请告诉我......

    常见的pjax调试

    • 调试工具栏是你的朋友。确保选中Chrome开发工具的网络标签中的preserve logs。否则,当页面重新加载时,您将忘记跟踪请求
    • 如果您看到请求中止,那么通常这表示上面的问题@ 2
    • 如果您发现请求返回的内容不是HTTP代码200,请检查Chrome开发工具中的响应预览。通常这会显示发生的异常。在这种情况下,您的问题是在服务器端。仔细检查你的php代码并修复它!
    • pjax-container中的链接是专门处理的。如果您希望它们触发周围的pjax-conatiner的刷新,请保持原样...否则将属性data-pjax="0"添加到它们。这表示如果单击此链接则不需要刷新。
    • 阅读文档...耗时5分钟:https://github.com/defunkt/jquery-pjax