managing document.ready event(s) on a large-scale website

后端 未结 9 1437
予麋鹿
予麋鹿 2021-01-30 10:51

NOTE: I have now created a jQuery plugin which is my attempt of a solution to this issue. I am sure that it could be improved and i\'ve probably overlooked lots of use c

相关标签:
9条回答
  • 2021-01-30 11:27

    "The problem is that we have one JS file"

    I'm not sure how you can avoid it as long as you are including the same (merged) JS file for all pages. You could use some server-side logic to merge different pieces to go with different pages, but then you presumably lose the benefits of client-side caching of the JS, so...

    Projects I've worked on have (typically) used multiple JS files, a couple being common to every page, and the others being included or not as appropriate - some JS files included by only one page. This means that pretty much every page includes the common library functions whether they use them or not, but the common JS file gets cached so it doesn't really matter. Page-specific code really is page-specific.

    I can't tell from your question whether you are aware of it, but you can have multiple document ready handlers (I believe jQuery executes them in the order they were bound?). So if you do split the JS up each JS file can include its own document ready. Of course that approach has its own overhead, but I think it's better than putting everything in the same file.

    0 讨论(0)
  • 2021-01-30 11:29

    I like the RameshVel approach. I also found the Paloma gem to create page-specific JavaScript. For instance:

    Paloma.controller('Admin/Users', {
      new: function(){
        // Handle new admin user
      }
    });
    
    0 讨论(0)
  • 2021-01-30 11:30

    I think the must intuitive solution to this problem is, simply, to reduce the amount of work performed at load time.

    If your code looks something like:

    $(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)
    });
    

    things should be relatively maintainable, even if there are a few dozen lines. There's no complicated/interesting logic at this level to update/remember when working with the component code and, because everything at this level is trivial, it's easy to read. At this point, there's no need to invent some complicated registration system; it's not going to be any simpler than .delegate and .each.

    Note as well that all of the above gracefully handles the case where the component is not used. In those cases, little or no work is done and no conditional logic is necessary.

    For interesting ideas about how you might implement the handlers/initializers, you might want to take a look at, for example, the "Contextual jQuery in practice" talk Doug Neiner gave at jQuery Boston last week.

    0 讨论(0)
  • 2021-01-30 11:31

    Firstly, if you're using jQuery, document.getElementsByTagName isn't really necessary, you can just use $("tagname"). Have a look at the jQuery Selectors documentation for even more magic!

    Your work-in-progress solution is the way I would go about it, but you don't need to go to the trouble of defining extra functions, getting bodyClasses, running a loop, or any of that jazz... why not just use jQuery's .hasClass() function?

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

    Bam. All you need. If you want to be even more efficient, you can reuse one body query:

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

    Here it is on jsfiddle: http://jsfiddle.net/W8nx8/6/

    0 讨论(0)
  • 2021-01-30 11:43

    This is what i have done in my rails mvc project with heavy javascript, i have created a separate namespace for the controllers in js which resembles the rails controller

    class BusinessController
       def new
       end  
       def index
       end
    end
    

    and

    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 
          }
    }
    

    and on the view code(server side) just initiate the page specific js code by

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

    You can pretty much tweak this to make it work in any language. And this approach doesn't care whether you have a single file or multiple files.

    0 讨论(0)
  • 2021-01-30 11:49

    First I put specific classes on the body or on specific containers e.g. articles, form-validation, password-meter, … . If I have an MVC app, I prefer to put the controller name into a body class. This does not hurt a lot and can be useful for styling, too.

    Then on each document.ready block I check for the existence of such a class, and if it does not exist I return from this function. This approach is simpler as it does not have the main code inside an if clause. This approach resembles to assertions that are used to check prerequisites of a function.

    Example:

    $(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
    });
    

    The bonus of this approach is that no unwanted code can sneak into a ready callback, which makes it easier to reuse. The downside is that you get many callback blocks and if you do not pay attention duplicate code can easily sneak into your app.

    0 讨论(0)
提交回复
热议问题