31

注: この問題の解決策として、jQuery プラグインを作成しました。私はそれが改善される可能性があると確信しており、おそらく多くのユースケースを見落としているので、フィードバックをしたい場合はお気軽に:-) https://github.com/WickyNilliams/ReadyBinder

私はそれ自体に問題はありませんが、これは議論の興味深いポイントになると思いました。人々がこれについていくつかの興味深いアイデアを持っていることを願っています.

基本的に、私は大規模な Web サイトで作業しており、ますます JavaScript を作成しています。これは問題ありません。私は JS のユニークなアプローチを楽しんでおり、言語のいくつかの暗い年表の風変わりさが魅力的だと感じています ;-) しかし、常に私を悩ませていることの 1 つは、ドキュメントの準備が整ったイベントがますます大きくなるにつれて、それらを管理する方法です。時間の経過とともに(結果として、提供されるページに焦点が合わなくなったり、特定されなくなったりします)

問題は、JS ファイルが 1 つしかないことです (私の質問では重要ではありませんが、マージおよび縮小されています)。ほとんどの JS は公開モジュール パターンを使用して記述されており、jQuery が選択したフレームワークです。したがって、すべての JS 機能は論理的にメソッドにグループ化され、名前空間が付けられ、スクリプト ファイルの一番下にこれがあります。

$(function(){
    //lots of code here, usually calling encapsulated methods 
    //on our namespaced revealing module
});

問題は、このドキュメント対応ハンドラーのすべてのコードがすべてのページに関連しているわけではないことです。たとえば、あるページでは 10% しか関連性がないかもしれませんが、別のページではおそらく 80% が関連しているかもしれません。私には、これは信じられないほど間違っているように感じます。主に効率のためだけでなく、保守性のためにも、ページごとに必要なコードのみを実行する必要があると感じています。

この問題へのアプローチをGoogleで検索しましたが、何も見つかりません。間違ったことを探しているだけかもしれません!

とにかく、私の質問は次のとおりです。

  • 誰もこの問題について考えたことがありますか?
  • それは実際に他の人々の意見の問題ですか?
  • コード内に大規模で包括的なドキュメント対応ハンドラーがありますか?それとも、提供されるページのタイプにより焦点を合わせていますか?
  • 後者の場合、これをどのように管理しますか? 複数のハンドラーが JS で切り替えられるか、サーバー側でドキュメント対応ハンドラーを動的に吐き出しますか?

この問題に関する人々の考えを楽しみにしています。

乾杯

4

9 に答える 9

9

これは、重いjavascriptを使用してRails MVCプロジェクトで行ったことです。Railsコントローラーに似たjsのコントローラー用に別の名前空間を作成しました

class BusinessController
   def new
   end  
   def index
   end
end

Var Business =  {
      init : function(action) {
         //code common to the Business module
         //even add the common jquery doc ready here, its clean
         //and call the page specific action
         this[action]();
      },
      new : function() {
             // check jquery document ready code here, thats relevant to this action
             //New rental page specific code here
      },
      index : function() {
             //  check jquery document ready code here, thats relevant to this action
             //index rental page specific code here 
      }
}

ビューコード(サーバー側)では、ページ固有のjsコードを開始するだけです

<script type="text/javascript"> 
 <%= controller_name %>.init('<%= controller.action_name %>'); 
//which will render to
//  Business.init(index);
</script>

これを微調整して、どの言語でも機能するようにすることができます。また、このアプローチでは、ファイルが 1 つであろうと複数であろうと関係ありません。

于 2011-09-30T03:59:26.050 に答える
2

この問題に対する直観的な解決策は、単純に、ロード時に実行される作業量を減らすことだと思います。

コードが次のようになっている場合:

$(function () {
    // Binds a single click event (which will never be triggered if the hypothetical
    // widget is never used), regardless of how many widgets are used on the page.
    $(document).delegate('.rating-widget', 'click', namespace.rating.handler);
    // and so on for similar things which simply require event handler registration

    // Initializes each of the forms on the page, letting the initializer take care
    // of any details (datepicker widgets, validation, etc) based on the root element
    $('form.fancy').each(namespace.fancyform.initializer);
    // and so on for similar things that require initialization

    // ... (for each type of thing on the page requiring initial setup,
    //      find the most general/high level pattern that sufficient)
});

数十行あったとしても、物事は比較的保守しやすいはずです。このレベルでは、コンポーネント コードを操作するときに更新または覚えておく必要のある複雑で興味深いロジックはありません。また、このレベルのすべてが簡単であるため、読みやすくなっています。この時点で、複雑な登録システムを考案する必要はありません。.delegateandよりも単純になることはありません.each

上記のすべてが、コンポーネントが使用されていない場合を適切に処理することにも注意してください。このような場合、作業はほとんどまたはまったく行われず、条件付きロジックは必要ありません。

ハンドラー/イニシャライザーの実装方法に関する興味深いアイデアについては、たとえば、先週 jQuery Boston で Doug Neiner が行った「 Contextual jQuery in practice 」の講演を参照してください。

于 2011-10-05T02:00:57.270 に答える
1

素晴らしい質問です。実際には、カスタム ページ ロード イベントを使用してこれを処理します。したがって、私のコア .js ファイルには、次のようなクラスがあります。

var Page = {
    init: function(pageName) {
        switch (pageName)
        {
            case: 'home': {
                // Run home page specific code
            }
            case: 'about': {
                // Run about page specific code
            }
            ...
        }
    }
}

$(document).ready()これは、ページ固有で、またはある種の URL パーサーを使用してコア スクリプトから、さまざまな方法で呼び出すことができます(文字通り、URL パーサーでは何でも可能です)。

$(document).ready(function() {
    // http://www.mydomain.com/about
    var currentPage = window.location.pathname;   // "about"
    Page.init(currentPage);    
});

window.locationDOM リファレンス: https://developer.mozilla.org/en/DOM/window.location

于 2011-09-30T03:33:57.147 に答える
1

最初に、特定のクラスを本体または特定のコンテナー (例: 、、、articlesform-validation)に配置password-meterします。MVC アプリを使用している場合は、コントローラー名を本体クラスに配置することを好みます。これはあまり害がなく、スタイリングにも役立ちます。

次に、各 document.ready ブロックでそのようなクラスの存在を確認し、存在しない場合はこの関数から戻ります。このアプローチは、if 句内にメイン コードがないため、より単純です。このアプローチは、関数の前提条件を確認するために使用されるアサーションに似ています。

例:

$(function(){
    if($('body').hasClass('articles') === false){ return; }

    //body of the articles code
});

$(function(){
    if($('body').hasClass('password-meter') === false){ return; }

    //include password meter in page
});

このアプローチの利点は、不要なコードが準備完了のコールバックに忍び込むことがないため、再利用が容易になることです。欠点は、多くのコールバック ブロックが発生することです。注意を怠ると、重複したコードがアプリに簡単に侵入する可能性があります。

于 2011-10-03T19:47:08.853 に答える
0

私はあなたがどこから来たのか知っています。モバイルでの使用に適した Web アプリケーションであるにもかかわらず、無関係なコードでいっぱいの大量の JS ファイルをユーザーにダウンロードさせるのはばかげていると感じるかもしれません (1 つの JQuery API は悪いスタートです!)。

私がしていることは、正しいか間違っているかもしれませんが、タグの前にページごとに必要な機能を含めることです。(この位置は、ほとんどの場合、document.ready の問題を回避します)。しかし、このアプローチは単純すぎると感じずにはいられません。

私は他の答えを聞くことに興味があるので、それは良い質問です+1.

于 2011-09-28T11:07:19.103 に答える
0

まず、jQuery を使用している場合、document.getElementsByTagName は実際には必要ありません。$("tagname") を使用できます。さらに魔法のjQuery セレクターのドキュメントを見てください!

あなたの進行中のソリューションは私がそれを行う方法ですが、追加の関数を定義したり、bodyClasses を取得したり、ループを実行したり、そのようなジャズを実行したりする必要はありません... jQuery の.hasClass()関数を使用しますか?

$(function() {
    if($("body").hasClass("article")) {
        alert("some article specific code");
    }
    if($("body").hasClass("landingPage")) {
        alert("some landing specific code");
    }
});

バム。必要なすべて。さらに効率的にしたい場合は、ボディ クエリを 1 つ再利用できます。

$(function() {
    var body = $("body");
    if(body.hasClass("article")) {
        alert("some article specific code");
    }
    if(body.hasClass("landingPage")) {
        alert("some landing specific code");
    }
});

これはjsfiddleにあります:http://jsfiddle.net/W8nx8/6/

于 2011-09-29T20:25:01.263 に答える
0

「問題は、JS ファイルが 1 つしかないことです」

すべてのページに同じ(マージされた)JSファイルを含めている限り、どうすれば回避できるかわかりません。サーバー側のロジックを使用して、さまざまな部分をマージしてさまざまなページに対応させることもできますが、そうすると、JS のクライアント側キャッシュの利点が失われる可能性があります。

私が取り組んできたプロジェクトでは (通常) 複数の JS ファイルを使用しており、2 つのファイルはすべてのページに共通であり、他のファイルは適切に含まれているかどうかに関係なく、1 つのページだけに含まれている JS ファイルもあります。これは、使用するかどうかに関係なく、ほぼすべてのページに共通のライブラリ関数が含まれていることを意味しますが、共通の JS ファイルはキャッシュされるため、それほど重要ではありません。ページ固有のコードは、実際にはページ固有です。

あなたの質問から、あなたがそれを認識しているかどうかはわかりませんが、複数のドキュメント対応ハンドラーを持つことができます (jQuery はバインドされた順序でそれらを実行すると思いますか?)。そのため、JS を分割すると、各 JS ファイルに独自のドキュメントをすぐに含めることができます。もちろん、そのアプローチには独自のオーバーヘッドがありますが、すべてを同じファイルに入れるよりはましだと思います。

于 2011-09-28T11:51:15.367 に答える
0

JavaScript ファイルを少なくすると、サーバーに送信されるリクエストの数が最小限に抑えられ、ファイルをキャッシュすることで、2 番目と 3 番目のページの読み込みが速くなります。通常、js ファイルの一部が次のページ (現在のページだけでなく) で必要になる可能性について考えます。これにより、js コードを 2 つのタイプに分類できます。「main.js」に入るコードと、使用されていなくてもクライアントによってダウンロードされるコード (ただし、必ずしも実行されるとは限りません。説明します) と、 2 番目のカテゴリのコードは、別のファイルに格納されます。実際には、確率でグループ化された複数のファイルを作成できます。これは、プロジェクトの詳細によって異なります。大規模なプロジェクトの場合、ユーザーの行動に関する統計分析を実行すると、js コードをグループ化する興味深い方法が明らかになる可能性があります。コードがクライアントにダウンロードされたので、すべてを実行する必要はありません。あなたがすべきことは、異なるレイアウトまたはページを持つことです。レイアウトまたはページにパーシャルを配置します。部分セット内に javascript 変数を設定します。javascript コード内の javascript 変数を取得し、コードを実行するかどうかを決定します。

すなわち:

部分的な "_stats.html.erb" を作成し、次のコードを配置します。

<script type="text/javascript">
    var collect_statistics = <%= collect_statistics %>;
</script>

統計を収集したいページにパーシャルを配置します: show.html.erb

<%= render "_stats", :collect_statistics => false %>

js ファイルで、次の操作を行います。

$(document).load( function() {
 if (typeof collect_statistics != "undefined" && collect_statistics) {
  // place code here
 }
});

これが役立つことを願っています!

于 2011-10-03T00:05:53.793 に答える