进出口创造谁与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内。
为了避免包括核心脚本两次
如果你的脚本已经通过包括较早前的要求,利用这一点避免再次包括它们:
// 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');
})
}
");
最简洁的方法是重写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文件名,不带路径。
为了避免包括脚本文件两次,试试这个扩展: http://www.yiiframework.com/extension/nlsclientscript/
为了避免附加事件处理两次,见容斯回答: https://stackoverflow.com/a/10188538/729324