but*_*ing 10 renderpartial clientscript yii
我正在创建一个使用ajaxRequest的网站,当我点击一个链接时,它将使用ajaxRequest加载.当我加载例如user/login UserController actionLogin时,我使用processOUtput将视图renderPartial设置为true,因此将生成该视图中所需的js,但是如果我在该视图中有clientScriptRegister,则如何避免生成scriptRegistered两次或多个取决于ajaxRequest?我试图Yii::app()->clientScript->isSCriptRegistered('scriptId')检查脚本是否已经注册,但似乎如果你使用了ajaxRequest,结果总是为false,因为它只在渲染完成后才为真.
控制器代码
if (Yii::app()->request->isAjaxRequest)
{
$this->renderPartial('view',array('model'=>$model),false,true);
}
Run Code Online (Sandbox Code Playgroud)
查看代码
if (!Yii::app()->clientScript->isScriptregistered("view-script"))
Yii::app()->clientScript->registerScript("view-script","
$('.link').live('click',function(){
alert('test');
})
");
Run Code Online (Sandbox Code Playgroud)
如果我是第一次请求控制器,它可以正常工作(警报1次)但如果我再次请求同一个控制器而不刷新我的页面并且只使用ajaxRequest,如果你单击它,警报将输出两次(因为它保持在你已经注册一次的情况下生成事件)
这是相同的,如果你有CActiveForm使用jQuery功能的观点.该corescript yiiactiveform将被调用每次你的RenderPartial内.
Jon*_*Jon 24
如果您的脚本已通过先前的请求包含在内,请使用此脚本以避免再次包含它们:
// 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;
Run Code Online (Sandbox Code Playgroud)
如果您有独立呈现的视图以及要包含在AJAX中的HTML片段,您可以将其包含在内部if (Yii::app()->request->isAjaxRequest)以涵盖所有基础.
还有可能阻止脚本在客户端被包含两次.这不是直接支持的,而且稍微麻烦一些,但在实践中它工作正常,并且它不需要您在服务器端知道客户端发生了什么(即已经包含哪些脚本).
我们的想法是从服务器获取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;
}
Run Code Online (Sandbox Code Playgroud)
如果已经包含相应的脚本,则会定义文件名和对象的映射; 通过此函数传递传入的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;
}
Run Code Online (Sandbox Code Playgroud)
您可以简单地使用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');
})
}
");
Run Code Online (Sandbox Code Playgroud)
最简洁的方法是覆盖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);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,您必须输入精确的js文件名,而不包含路径.