YII的RenderPartial(proccessoutput =真)避免重复JS请求(Yii r

2019-06-23 16:55发布

进出口创造谁与ajaxRequest工作的网站,当我点击一个链接,它会加载使用ajaxRequest。 当我加载例如用户/登录UserController中actionLogin,我的RenderPartial与processOUtput视图为true,以便视图内所需要的JS将产生,但是,如果我有clientScriptRegister与事件视图内,如何避免以产生scriptRegistered两次或多个取决于ajaxRequest? 我已经试过Yii::app()->clientScript->isSCriptRegistered('scriptId')来检查脚本已经注册但似乎如果你使用ajaxRequest, 结果始终是假的 ,因为它只会后的真实渲染完成。

控制器代码

if (Yii::app()->request->isAjaxRequest)
{
   $this->renderPartial('view',array('model'=>$model),false,true);
}

查看代码

if (!Yii::app()->clientScript->isScriptregistered("view-script"))
   Yii::app()->clientScript->registerScript("view-script","
      $('.link').live('click',function(){
         alert('test');
     })
");

如果我请求控制器的第一次,它完美的作品(警告1次),但如果我再次请求相同的控制器而无需刷新我的网页,只是使用ajaxRequest,警报将输出两次,如果你点击它(因为它使上eventhough生成您已经注册一次)

这是相同的,如果你有CActiveForm使用jQuery功能的观点。该corescript yiiactiveform将被调用每次你的RenderPartial内。

Answer 1:

为了避免包括核心脚本两次

如果你的脚本已经通过包括较早前的要求,利用这一点避免再次包括它们:

// For jQuery core, Yii switches between the human-readable and minified
// versions based on DEBUG status; so make sure to catch both of them
Yii::app()->clientScript->scriptMap['jquery.js'] = false;
Yii::app()->clientScript->scriptMap['jquery.min.js'] = false;

如果您有被渲染视图既独立和被包含在AJAX HTML片段,你可以用这里面if (Yii::app()->request->isAjaxRequest)覆盖所有基地。

为了避免包括两次jQuery的脚本(JS溶液)

还有防止被包含脚本两次在客户端的可能性。 这是不直接支持及略微更繁琐,但在实践中它工作得很好,它不需要你知道在服务器端发生了什么事情在客户端(即哪些脚本已经被包括在内)。

这个想法是从服务器获取HTML,只是去掉了<script>用正则表达式标记替代。 最重要的一点是,如果jQuery的核心脚本和插件已经被加载,你可以检测到(因为他们创造$它或属性),并为此条件:

function stripExistingScripts(html) {
    var map = {
        "jquery.js": "$",
        "jquery.min.js": "$",
        "jquery-ui.min.js": "$.ui",
        "jquery.yiiactiveform.js": "$.fn.yiiactiveform",
        "jquery.yiigridview.js": "$.fn.yiiGridView",
        "jquery.ba-bbq.js": "$.bbq"
    };

    for (var scriptName in map) {
        var target = map[scriptName];
        if (isDefined(target)) {
            var regexp = new RegExp('<script.*src=".*' +
                                    scriptName.replace('.', '\\.') +
                                    '".*</script>', 'i');
            html = html.replace(regexp, '');
        }
    }

    return html;
}

有图的文件名和将,如果相应的脚本已包括已定义的对象; 通过这个功能将您的来电HTML,它会检查并删除<script>对应于先前加载脚本标签。

助手功能isDefined是这样的:

function isDefined(path) {
    var target = window;
    var parts = path.split('.');

    while(parts.length) {
        var branch = parts.shift();
        if (typeof target[branch] === 'undefined') {
            return false;
        }

        target = target[branch];
    }

    return true;
}

为了避免附加的事件处理程序两次

你可以简单地使用JavaScript对象要记住,如果你已经连接的处理程序; 如果是,不要再附上。 例如(图代码):

Yii::app()->clientScript->registerScript("view-script","
  window.myCustomState = window.myCustomState || {}; // initialize if not exists
  if (!window.myCustomState.liveClickHandlerAttached) {
    window.myCustomState.liveClickHandlerAttached = true;
    $('.link').live('click',function(){
       alert('test');
    })
  }
");


Answer 2:

最简洁的方法是重写beforeAction(),以避免任何重复的核心脚本:

class Controller extends CController {

  protected function beforeAction($action) {
        if( Yii::app()->request->isAjaxRequest ) {
            Yii::app()->clientScript->scriptMap['jquery.js'] = false;
            Yii::app()->clientScript->scriptMap['jquery-2.0.0.js'] = false;
            Yii::app()->clientScript->scriptMap['anything.js'] = false;
        }

        return parent::beforeAction($action);
  }

}

请注意,你必须把确切的js文件名,不带路径。



Answer 3:

为了避免包括脚本文件两次,试试这个扩展: http://www.yiiframework.com/extension/nlsclientscript/

为了避免附加事件处理两次,见容斯回答: https://stackoverflow.com/a/10188538/729324



文章来源: Yii renderpartial (proccessoutput = true) Avoid Duplicate js request