10

ajaxRequestで動作するサイトを作成しています。リンクをクリックすると、ajaxRequestを使用して読み込まれます。たとえばuser/login UserController actionLoginをロードすると、processOUtputをtrueに設定してビューをrenderPartialにすると、そのビュー内に必要なjsが生成されますが、イベントを含むビュー内にclientScriptRegisterがある場合、scriptRegisteredを2回生成しないようにするにはどうすればよいですか?またはajaxRequestに応じて複数?Yii::app()->clientScript->isSCriptRegistered('scriptId')スクリプトがすでに登録されているかどうかを確認しようとしましたが、ajaxRequestを使用した場合、レンダリングが終了した後にのみtrueになるため、結果は常に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を使用して同じコントローラーを再度リクエストした場合、クリックするとアラートが2回出力されます(すでに一度登録していても生成時)

これは、jquery機能を備えたビュー内にCActiveFormがある場合も同じです。コアスクリプトyiiactiveformは、renderPartialを実行するたびに呼び出されます。

4

3 に答える 3

24

コアスクリプトを2回含めないようにする

以前のリクエストでスクリプトがすでに含まれている場合は、これを使用して、スクリプトが再度含まれないようにします。

// 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スクリプトが2回含まれないようにするため(JSソリューション)

スクリプトがクライアント側に2回含まれるのを防ぐ可能性もあります。これは直接サポートされておらず、少し面倒ですが、実際には正常に機能し、サーバー側でクライアント側で何が起こっているか(つまり、どのスクリプトがすでに含まれているのか)を知る必要はありません。

アイデアは、サーバーから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;
}

イベントハンドラーを2回アタッチしないようにする

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');
    })
  }
");
于 2012-04-17T09:23:43.423 に答える
6

最もクリーンな方法は、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ファイル名を入力する必要があることに注意してください。

于 2013-06-11T20:10:06.563 に答える
4

スクリプトファイルが2回含まれないようにするには、次の拡張機能を試してください:http ://www.yiiframework.com/extension/nlsclientscript/

イベントハンドラーを2回アタッチしないようにするには、Jonsの回答を参照してください:https ://stackoverflow.com/a/10188538/729324

于 2013-01-31T09:22:19.993 に答える