避免两次包含核心脚本
如果您的脚本已经通过较早的请求包含在内,请使用它来避免再次包含它们:
// 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 解决方案)
还有可能防止脚本在客户端被包含两次。这不是直接支持的,而且稍微麻烦一些,但实际上它可以正常工作,并且不需要您在服务器端知道客户端发生了什么(即已经包含了哪些脚本)。
<script>
这个想法是从服务器获取 HTML,然后用正则表达式替换简单地去除标签。重要的一点是您可以检测是否已经加载了 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');
})
}
");