Yii renderpartial(proccessoutput=true) Evite la solicitud de js duplicados
clientscript (3)
Im creando un sitio que trabaja con ajaxRequest, cuando hago clic en un enlace, se carga usando ajaxRequest. Cuando cargo, por ejemplo, user / login UserController actionLogin , visualizo Partial la vista con processOUtput en true, por lo que se generarán los js necesarios dentro de esa vista; sin embargo, si tengo clientScriptRegister dentro de esa vista con eventos, ¿cómo puedo evitar generar el script? o múltiples dependiendo de ajaxRequest? He intentado Yii::app()->clientScript->isSCriptRegistered(''scriptId'')
para comprobar si el script ya está registrado, pero parece que si usaste ajaxRequest, el resultado siempre será falso porque solo será verdadero después del el render está terminado.
Código de controlador
if (Yii::app()->request->isAjaxRequest)
{
$this->renderPartial(''view'',array(''model''=>$model),false,true);
}
Ver código
if (!Yii::app()->clientScript->isScriptregistered("view-script"))
Yii::app()->clientScript->registerScript("view-script","
$(''.link'').live(''click'',function(){
alert(''test'');
})
");
Si solicito el controlador por primera vez, funciona perfectamente (alerta 1 vez) pero si solicito nuevamente para ese mismo controlador sin actualizar mi página y simplemente usando ajaxRequest, la alerta generará dos veces si hace clic en él (porque mantiene en generar aunque ya lo registraste una vez)
Esto es lo mismo si tiene CActiveForm dentro de la vista con la funcionalidad de jquery. Se invocará la forma yiiactive corescript cada vez que representePartial.
Para evitar incluir scripts principales dos veces
Si sus scripts ya se han incluido a través de una solicitud anterior, use esto para evitar incluirlos de nuevo:
// 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;
Si tiene vistas que se están renderizando de forma independiente y como fragmentos HTML para ser incluidas con AJAX, puede envolver esto dentro if (Yii::app()->request->isAjaxRequest)
cubre todas las bases.
Para evitar incluir scripts jQuery dos veces (solución JS)
También existe la posibilidad de evitar que los guiones se incluyan dos veces en el lado del cliente. Esto no es soportado directamente y es un poco más engorroso, pero en la práctica funciona bien y no requiere que sepa por el lado del servidor qué está sucediendo en el lado del cliente (es decir, qué scripts ya se han incluido).
La idea es obtener el HTML del servidor y simplemente quitar las etiquetas <script>
con la sustitución de expresiones regulares. El punto importante es que puede detectar si los scripts y complementos jQuery core ya se han cargado (porque crean $
o propiedades en él) y lo hacen condicionalmente:
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;
}
Hay un mapa de nombres de archivos y objetos que se habrá definido si el script correspondiente ya se ha incluido; pase su HTML entrante a través de esta función y comprobará y eliminará las etiquetas <script>
que corresponden a las secuencias de comandos cargadas previamente.
La función isDefined
está isDefined
es esto:
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;
}
Para evitar unir controladores de eventos dos veces
Simplemente puede usar un objeto Javascript para recordar si ya ha adjuntado el controlador; si es así, no lo adjunte de nuevo. Por ejemplo (ver código):
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'');
})
}
");
La forma más limpia es anular beforeAction (), para evitar cualquier secuencia de comandos central duplicada:
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);
}
}
Tenga en cuenta que debe poner el nombre exacto del archivo js, sin la ruta.
Para evitar incluir archivos de script dos veces, intente con esta extensión: http://www.yiiframework.com/extension/nlsclientscript/
Para evitar adjuntar controladores de eventos dos veces, vea la respuesta de Jons: https://.com/a/10188538/729324