Organization and initialization of UJS code

My two-part question is what seems very simple, but I have not seen any discussions in introductions, tutorials, or reviews in UJS or jQuery. I read a lot of other topics / questions to try and find examples that I could just copy the style or feel, but examples of toys that ask: "How do I make X in jQuery?" and the like, never explain or demonstrate how their solutions are suitable for wider application.

So my question is structural or architectural.

In versions of 'tl; dr ' questions are mostly asked: "How do people actually organize and initialize unobtrusive JavaScript code in large applications?" In particular:

  • "When writing JavaScript in an unobtrusive style, how can code be organized through files? Should it be executed?" (I understand that there are advantages only to sending one file to the client, which is then cached, and all subsequent downloads are faster).

  • "If the corresponding JS is no longer explicitly loaded by the page, how can I make sure that the correct code is correctly initialized / called / used on the corresponding pages, and that time is not wasted launching selectors that are not related to the current page?"

Long version:

After several months of manual work of my own fragile, good enough for JavaScript now in our Rails application, I finally move on to the path of UJS and jQuery. Now I have read all of http://jqfundamentals.com , except for the "Advanced Topics" section. I get jQuery freezes quite easily, and my pages do what I want in isolation.

As for “unobtrusive JavaScript,” I’m less clear, but the idea seems to be that first of all, splitting JS completely external files and linking JS functionality to the page after the fact by determining which page you are on and the attachment function after the document is ready . Please correct me if this is inaccurate or incomplete.

But I don’t understand how to organize my code and make sure that the correct JavaScript is enabled and attached to the correct pages. All the methods that I can imagine seem either extremely inefficient, or inconvenient, or invalid, some of the principles of UJS.

The current state of affairs is that I have a massive and cumbersome application.js file, in which all kinds of selectors are clogged, which expect functionality to be placed on page elements that are not 90% of my pages. That is, on pages 1 there are elements A, B and C, while in paragraphs A, D and E. this often leads to a rupture of things. I feel that I have two unpleasant options left:

  • Since I want the server to send only one large .js file, all my JS code in application.js is somehow wrapped in a switch statement that determines (?) Which page it is on and does only document.ready invokes elements that he knows should be on this page. The obvious ways I could handle this are very ugly, like putting a single JS variable inside a page and checking it, which breaks all the zen UJS that attracted me in the first place.

  • Separate my JavaScript into different files and selectively download them. That is, "I'm in view01.html.erb, so I need to include view01.js", which only deals with elements on view01.html.erb. It seems better at first, but it gets awkward when it comes to partial files, mixes and .js comparisons and trying to stay dry.

I went down this UJS path because he had this very clean, zen appeal, but for a larger project, there seemed to be more problems than it was worth. However, people are much smarter than me insist on something else, and I completely agree that the built-in and script-tag-bound JavaScript is awkward and ugly, which makes me believe that I'm doing something wrong.

What I have done so far (aka Even Longer Version is probably not worth your time to read):

Stage 1: I am working on a Rails application, so I started with the route presented in several RailsCasts tutorials that demonstrate the code in application.js that finds the element through a selector and attaches some functions to it. Everything worked perfectly, and I had 2 or 3 pages that made all the great jQuery, Web2.0-ish, AJAX-y, which are hot with the kids these days. Excellent!

Phase 2: Then I made another page and it all started. I had all my code in application.js, access to which through $ ('selector'). There was not a single element on this new page, as on other pages, so when my code from other pages tries to get an element with id = 'special_area', the call $ ('# special_area') [0] breaks because it is empty . Null checking the result of each individual selector did not feel right, so I ended up with a decision not to use DOM elements that I know and love, but work with these fancy jQuery objects that can be connected by a chain. Well maintained.

Phase 3: I understand that with these JQuery Chained objects, as long as all my identifiers are unique, or I put some unique DIV on each page, any elements that do not exist on the page will return an empty set and (hopefully) will not break. I don’t know enough to say for sure that they will not break, no matter what I want to do with them, because they are empty, so I am not going to assume that this is so. But somehow I see how it works slightly by clicking ALL elements in my entire application and somehow reasonably ignoring elements that do not exist on the current page.

In addition, the JQuery Fundamentals manual discusses many times how expensive it is to work with selectors. And if I just redirect ALL of my selectors and not apply those that don't exist, I put HUGE static overhead on every page, as as my application grows, .js, and each page needs to check more and more elements, which are not actually displayed on it!

Stage 4: I learned about how namespaces are executed in JS, and while I plan to use them, I do not see this as a solution to this particular problem. If they can, please explain. In addition, my ability to articulate my frustration and confusion has broken, and I wonder how people actually organize and initialize UJS code in Real Life ™?

+4
source share
1 answer

tl; dr Answer

  • Divide your code into AMD modules, load them using the AMD loader, for example RequireJS . And yes, that must be done.
  • In partial form, just require() and execute the appropriate module

Longer answer

Using an AMD loader, such as RequireJS , allows you to copy code into separate modules. You can also save common code (e.g. jQuery) in a common module, and then use it as a prerequisite for your view modules.

You can read the Definition of the asynchronous module , RequireJS and using it with jQuery , but this is how I approach it:

  • You have the main document to enable and configure your AMD loader. You will probably want to load common modules (jQuery, etc.) so that the browser can cache them between requests.
  • For each partial representation implements the corresponding JS-module .
  • In a partial view, add a script block to load the module and execute its initialization function

View module

Your module will look something like this (we use jQuery as an AMD module):

 js/partials/view01.js define(["jquery", function($) { "use strict"; return { init: function() { // This is where you do your UJS work for this partial // ... } } }); 

Partial view

In a partial view, you load the module and call the init function:

 view01.html.erb <script> require("partials/view01", function(view) { view.init(); }); </script> <!-- More HTML for this partial view --> 
0
source

Source: https://habr.com/ru/post/1392292/


All Articles