Yii renderpartial (proccessoutput = true) избегайте дублирования запроса js
Im создание сайта, который работает с ajaxRequest, когда я нажимаю ссылку, он загружается с помощью ajaxRequest. Когда я загружаю, например, user / login actionLogin UserController, Я renderPartial представление с processOUtput в true так Яш нужна внутри, что вид будет, однако если я clientScriptRegister внутри представления событий, как я могу избежать создания scriptRegistered два или несколько в зависимости от ajaxRequest? Я пробовал Yii::app()->clientScript->isSCriptRegistered('scriptId')
чтобы проверить, зарегистрирован ли скрипт, но кажется, что если вы использовали ajaxRequest,результат всегда false потому что это будет верно только после завершения рендеринга.
контроллер код
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.
3 ответов
чтобы избежать включения основных скриптов дважды
если ваши скрипты уже были включены через более ранний запрос, используйте это, чтобы избежать их повторного включения:
// 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 core скрипты и плагины уже загружены (потому что они создают $
или свойства на нем) и сделайте это условно:
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/
чтобы избежать присоединения обработчиков событий дважды, см. ответ Jons:https://stackoverflow.com/a/10188538/729324