Ответ 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;
Если у вас есть представления, которые отображаются как самостоятельно, так и как HTML-фрагменты, которые должны быть включены в AJAX, вы можете обернуть это внутри 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;
}
Существует карта имен файлов и объектов, которые будут определены, если соответствующий script уже включен; передайте входящий 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');
})
}
");