Yii renderpartial(proccessoutput=true)避免重复js请求
我正在创建一个使用ajaxRequest的站点,当我单击一个链接时,它将使用ajaxRequest加载。当我加载例如user/login UserController actionLogin时,我将processOUtput的部分视图渲染为true,以便生成该视图中所需的js,但是如果我在该视图中使用事件注册clientScriptRegister,我如何避免根据ajaxRequest生成两次或多次scriptRegistered?我尝试了Yii renderpartial(proccessoutput=true)避免重复js请求,yii,renderpartial,clientscript,Yii,Renderpartial,Clientscript,我正在创建一个使用ajaxRequest的站点,当我单击一个链接时,它将使用ajaxRequest加载。当我加载例如user/login UserController actionLogin时,我将processOUtput的部分视图渲染为true,以便生成该视图中所需的js,但是如果我在该视图中使用事件注册clientScriptRegister,我如何避免根据ajaxRequest生成两次或多次scriptRegistered?我尝试了Yii::app()->clientScript->is
Yii::app()->clientScript->isSCriptRegistered('scriptId')
来检查脚本是否已注册,但如果使用ajaxRequest,则结果始终为false,因为只有在渲染完成后才会为true
控制器代码
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,如果您单击它,警报将输出两次(因为它会继续生成事件,尽管您已经注册了一次)
如果在具有jquery功能的视图中有CActiveForm,则情况也是如此。。每次渲染Partial时都会调用corescript yiiactiveform。以避免包含两次核心脚本
如果您的脚本已通过先前的请求包含,请使用此选项避免再次包含它们:
// 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;
如果您有独立呈现的视图以及作为HTML片段包含在AJAX中的视图,那么您可以将其包装在If(Yii::app()->request->isAjaxRequest)
中,以覆盖所有基础
避免两次包含jQuery脚本(JS解决方案)
还可以防止脚本在客户端被包含两次。这是不直接支持的,而且有点麻烦,但在实践中,它工作得很好,并且不需要您知道服务器端在客户端发生了什么(即,已经包含了哪些脚本)
其思想是从服务器获取HTML,并用正则表达式replace简单地去掉
标记。重要的一点是,您可以检测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;
}
避免两次附加事件处理程序
您可以简单地使用Javascript对象来记住是否已经附加了处理程序;如果是,请不要再次连接。例如(视图代码):
要避免两次包含脚本文件,请尝试此扩展名:
要避免两次附加事件处理程序,请参见Jons的答案:最干净的方法是重写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文件名,而不包括路径。对于诸如yiiactiveform之类的核心脚本如何?jquery?顺便说一下,谢谢。这是
window.myCustomState=window.myCustomState | |{}代码>在js中创建对象的简写?@butching:有关CoreScript,请参阅更新。对于对象创建语法,如果(!window.myCustomState)window.myCustomState={}
为避免两次包含核心脚本-->是,我使用该脚本删除核心脚本,但我的问题是,如果两个请求都是ajax,您如何知道该脚本已经包含在早期请求中?因为正如我前面所说的,在ajaxRequest中创建对象的结果总是错误的,是的,它很可爱,我明白了。。thx@butching:嗨,我用一个附加选项更新了答案。这会对已在主布局上初始化的已注册脚本产生影响吗?还是我必须在config main中注册脚本?实际上,您不应该在主布局中硬编码脚本(除非您确实需要).非常感谢您的反馈
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');
})
}
");
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);
}
}