O ile mi wiadomo, wszystkie skrypty JavaScript zostają scalone w jeden plik. Rails robi to domyślnie, gdy dodaje //= require_tree .
się do dolnej części application.js
pliku manifestu.
To brzmi jak prawdziwa oszczędność życia, ale trochę martwię się o specyficzny dla strony kod JavaScript. Czy ten kod jest wykonywany na każdej stronie? Ostatnią rzeczą, jakiej chcę, jest tworzenie instancji wszystkich moich obiektów dla każdej strony, gdy są one potrzebne tylko na 1 stronie.
Ponadto, czy nie ma też potencjału do konfliktu kodu?
A może umieścisz mały script
tag na dole strony, który po prostu wywołuje metodę, która wykonuje kod javascript dla strony?
Czy nie potrzebujesz już wtedy pliku.j.j?
Dzięki
EDYCJA : Doceniam wszystkie odpowiedzi ... i nie sądzę, że tak naprawdę mają problem. Niektóre z nich dotyczą stylizacji i nie wydają się odnosić do innych ... a inne po prostu wspominają javascript_include_tag
... o których wiem, że istnieją (oczywiście ...), ale wydaje się, że drogą do Rails 3.1 jest zakończenie wszystkich JavaScript w jednym pliku zamiast ładowania pojedynczego JavaScript na dole każdej strony.
Najlepszym rozwiązaniem, jakie mogę wymyślić, jest zawinięcie niektórych funkcji w div
tagi za pomocą id
s lub class
es. W kodzie JavaScript wystarczy sprawdzić, id
czy class
na stronie jest ikona lub, a jeśli tak, uruchom kod JavaScript, który jest z nią powiązany. W ten sposób, jeśli elementu dynamicznego nie ma na stronie, kod JavaScript nie działa - nawet jeśli został zawarty w ogromnym application.js
pliku spakowanym przez Sprockets.
Moje powyższe rozwiązanie ma tę zaletę, że jeśli pole wyszukiwania znajduje się na 8 ze 100 stron, będzie działać tylko na tych 8 stronach. Nie musisz także umieszczać tego samego kodu na 8 stronach w witrynie. W rzeczywistości nigdy więcej nie będziesz musiał umieszczać ręcznych tagów skryptowych w swojej witrynie.
Myślę, że to jest właściwa odpowiedź na moje pytanie.
application.js
), a podane przez ciebie odniesienie wskazuje, dlaczego tak jest: pobieranie jest najwolniejsza część procesu wykonywania JS. Wiele małych plików jest bardziej buforowalnych niż jeden duży. Ludzie z Unholy Rails nie zdają sobie zatem sprawy z tego, że ich rekomendacje są niezgodne z zasadami, których starają się przestrzegać, i dlatego ich rekomendacje nie powinny być traktowane poważnie.Odpowiedzi:
Dokumenty potoku zasobów sugerują, jak wykonać JS specyficzne dla kontrolera:
Link do: rurociąg_zasobów
źródło
page_specific_js = "#{params[:controller]}_#{params[:action]}"
i wtedy;javascript_include_tag page_specific_js if Rails.application.assets.find_asset page_specific_js
W przypadku stron specyficznych dla strony można użyć rozwiązania Garber-Irish .
Tak więc folder javascripts w Railsach może wyglądać tak dla dwóch kontrolerów - samochodów i użytkowników:
A javascripts będą wyglądać następująco:
a markup_based_js_execution będzie zawierał kod dla obiektu UTIL, a na wykonanie UTIL.init gotowe do DOM.
I nie zapomnij umieścić tego w pliku układu:
Myślę również, że lepiej jest używać klas zamiast
data-*
atrybutów, aby uzyskać lepszy css specyficzny dla strony. Jak wspomniał Jason Garber: selektory CSS specyficzne dla strony mogą być naprawdę niewygodne (gdy używaszdata-*
atrybutów)Mam nadzieję, że to Ci pomoże.
źródło
window.varForOneController='val'
w tej funkcji inicjującej kontroler. Pomocny może być również gem gem ( github.com/gazay/gon ). Mogą istnieć inne obejścia.//= require_tree .
JavaScript i używać specyficznego dla strony JavaScript. Jeśli aktywnie próbujesz tego nie robić, to dążysz do złych praktyk.Widzę, że odpowiedziałeś na własne pytanie, ale oto inna opcja:
Zasadniczo zakładasz, że
jest wymagane. To nie jest. Możesz go usunąć. W mojej bieżącej aplikacji, po raz pierwszy, szczerze mówiąc, stworzyłem trzy różne pliki JS najwyższego poziomu. Mój
application.js
plik ma tylkoW ten sposób mogę tworzyć podkatalogi z własnymi plikami JS najwyższego poziomu, które zawierają tylko to, czego potrzebuję.
Klucze to:
require_tree
- Railsy pozwalają zmienić przyjęte założeniaapplication.js
- każdy plik wassets/javascript
podkatalogu może zawierać dyrektywy poprzedzające procesor//=
Mam nadzieję, że to pomaga i dodaje pewne szczegóły do odpowiedzi ClosureCowboy.
Sujal
źródło
//= require_tree .
z//= require_directory .
tak można zachować wszystkie istniejące pliki, gdzie one są i tworzyć nowe katalogi dla strona konkretnych plików.Inna opcja: aby utworzyć pliki specyficzne dla strony lub modelu, możesz utworzyć katalogi w swoim
assets/javascripts/
folderze.Główny
application.js
plik manifestu można skonfigurować tak, aby ładował jego plikiglobal/
. Określone strony lub grupy stron mogą mieć własne manifesty, które ładują pliki z ich własnych katalogów. Koła zębate automatycznie połączą ładowane plikiapplication.js
z plikami specyficznymi dla strony, co pozwala na działanie tego rozwiązania.Tę technikę można również zastosować
style_sheets/
.źródło
Doceniam wszystkie odpowiedzi ... i nie sądzę, aby naprawdę rozwiązywały ten problem. Niektóre z nich dotyczą stylizacji i nie wydają się odnosić do innych ... a inne po prostu wspominają
javascript_include_tag
... o których wiem, że istnieją (oczywiście ...), ale wydaje się, że drogą do Rails 3.1 jest zakończenie wszystkich JavaScript w jednym pliku zamiast ładowania pojedynczego Javascript na dole każdej strony.Najlepszym rozwiązaniem, jakie mogę wymyślić, jest zawinięcie niektórych funkcji w
div
tagi za pomocąid
s lubclass
es. W kodzie javascript. Następnie po prostu sprawdzasz,id
czyclass
na stronie jest ikona lub, a jeśli tak, to uruchamiasz powiązany z nią kod javascript. W ten sposób, jeśli elementu dynamicznego nie ma na stronie, kod javascript nie działa - nawet jeśli został zawarty w ogromnymapplication.js
pliku spakowanym przez Sprockets.Moje powyższe rozwiązanie ma tę zaletę, że jeśli pole wyszukiwania znajduje się na 8 ze 100 stron, będzie działać tylko na tych 8 stronach. Nie musisz także umieszczać tego samego kodu na 8 stronach w witrynie. W rzeczywistości nigdy więcej nie będziesz musiał umieszczać ręcznych tagów skryptowych w swojej witrynie - z wyjątkiem być może danych wstępnego ładowania.
Myślę, że to jest właściwa odpowiedź na moje pytanie.
źródło
<script>
tagi. Tak, klasy i identyfikatory są częścią odpowiedzi, ale nie ma sensu, aby użytkownik ładował JavaScript, którego ta strona nie wymaga.Zdaję sobie sprawę, że przychodzę na tę imprezę trochę później, ale chciałem wprowadzić rozwiązanie, którego ostatnio używałem. Najpierw jednak wspomnę ...
The Rails 3.1 / 3.2 Way (Nie, proszę pana. Nie podoba mi się.)
Zobacz: http://guides.rubyonrails.org/asset_pipeline.html#how-to-use-the-asset-pipeline
Podaję poniższe w celu zapewnienia kompletności w tej odpowiedzi, a ponieważ nie jest to nieopłacalne rozwiązanie ... chociaż nie dbam o to zbytnio.
„Rails Way” jest rozwiązaniem zorientowanym na kontroler, a nie zorientowanym na widok, jak zażądał pierwotny autor tego pytania. Istnieją pliki JS specyficzne dla kontrolera, nazwane na cześć odpowiednich kontrolerów. Wszystkie te pliki są umieszczone w drzewie folderów, które NIE są domyślnie zawarte w żadnej wymaganej przez aplikację.js.
Aby dołączyć kod specyficzny dla kontrolera, do widoku dodano następujące elementy.
Nienawidzę tego rozwiązania, ale ono istnieje i jest szybkie. Prawdopodobnie można zamiast tego nazwać te pliki czymś w rodzaju „people-index.js” i „people-show.js”, a następnie użyć czegoś takiego,
"#{params[:controller]}-index"
aby uzyskać rozwiązanie zorientowane na widok. Znowu szybka naprawa, ale to nie pasuje do mnie.My Data Attribute Way
Nazywaj mnie szalonym, ale chcę, aby WSZYSTKIE moje JS zostały skompilowane i zminimalizowane w pliku application.js podczas wdrażania. Nie chcę pamiętać, aby w każdym miejscu umieścić te małe pliki maruderów.
Ładuję wszystkie moje JS w jednym kompaktowym, niedługo buforowanym pliku przeglądarki. Jeśli jakiś fragment pliku application.js wymaga uruchomienia na stronie, pozwalam HTMLowi powiedzieć, a nie Railsom.
Zamiast blokować mój JS do określonych identyfikatorów elementów lub zaśmiecać mój HTML klasami znaczników, używam niestandardowego atrybutu danych o nazwie
data-jstags
.Na każdej stronie używam - wstaw tutaj preferowaną metodę biblioteki JS - aby uruchomić kod po zakończeniu ładowania DOM. Ten kod ładowania początkowego wykonuje następujące działania:
data-jstag
Powiedzmy, że mam gdzieś w mojej pliku application.js:
Zdarzenie ładowania początkowego zastosuje funkcje
my_autosuggest_init
i wmy_hint_init
stosunku do danych wejściowych wyszukiwania, zamieniając je w dane wejściowe, które wyświetlają listę sugestii podczas pisania przez użytkownika, a także zapewniają pewien rodzaj wskazówek wejściowych, gdy dane wejściowe są puste i nie są skoncentrowane.O ile jakiś element nie jest oznaczony
data-jstag="auto-suggest"
, kod autosugestii nigdy nie zostanie uruchomiony. Jednak zawsze tam jest, zminimalizowany i ostatecznie buforowany w mojej application.js na te czasy, kiedy potrzebuję go na stronie.Jeśli musisz przekazać dodatkowe parametry do oznaczonych funkcji JS, musisz zastosować trochę kreatywności. Dodaj atrybuty parametrów danych, wymyśl jakąś składnię parametrów, a nawet zastosuj podejście hybrydowe.
Nawet jeśli mam skomplikowany obieg pracy, który wydaje się specyficzny dla kontrolera, po prostu utworzę dla niego plik w folderze lib, spakuję go do pliku application.js i oznaczy go słowem „kreator nowych rzeczy”. Kiedy mój bootstrap trafi w ten tag, mój miły, fantazyjny kreator zostanie utworzony i uruchomiony. W razie potrzeby działa dla widoków tego kontrolera, ale nie jest w inny sposób sprzężony z kontrolerem. W rzeczywistości, jeśli poprawnie koduję mojego kreatora, być może będę w stanie dostarczyć wszystkie dane konfiguracyjne w widokach, a zatem będę mógł ponownie użyć mojego kreatora później dla dowolnego innego kontrolera, który tego potrzebuje.
Tak czy inaczej, od pewnego czasu wdrażam JS specyficzne dla strony i dobrze mi to służyło zarówno w przypadku prostych projektów witryn, jak i bardziej złożonych / bogatych aplikacji. Mam nadzieję, że jedno z dwóch rozwiązań, które tu przedstawiłem, na swój sposób lub na Railsach, jest pomocne dla każdego, kto napotka to pytanie w przyszłości.
źródło
Odpowiedź została zaakceptowana i zaakceptowana dawno temu, ale wymyśliłem własne rozwiązanie oparte na niektórych z tych odpowiedzi i moim doświadczeniu z Rails 3+.
Rurociąg zasobów jest słodki. Użyj tego.
Po pierwsze, w twoim
application.js
usuń pliku//= require_tree.
Następnie w swojej
application_controller.rb
metodzie pomocniczej:Następnie w
application.html.erb
pliku układu dodaj nowego pomocnika spośród istniejących dołączonych skryptów javascript, poprzedzonychraw
pomocnikiem:Voila, teraz możesz łatwo tworzyć javascript specyficzny dla widoku, używając tej samej struktury plików, której używasz wszędzie indziej w szynach. Po prostu włóż swoje pliki
app/assets/:namespace/:controller/action.js.erb
!Mam nadzieję, że pomoże to komuś innemu!
źródło
<%= raw ... %>
zwróci 404?require_tree /
(zły)?Możesz dodać ten wiersz do pliku układu (np. Application.html.erb), aby automatycznie załadować konkretny plik javascript dla kontrolera (ten, który został utworzony podczas generowania kontrolera):
Możesz także dodać wiersz, aby automatycznie ładować plik skryptu dla poszczególnych działań.
Po prostu umieść skrypty strony w podkatalogu nazwanym na cześć nazwy kontrolera. W tych plikach możesz dołączyć inne skrypty używając = wymagaj. Byłoby miło stworzyć pomocnika, który będzie dołączał plik tylko wtedy, gdy on istnieje, aby uniknąć awarii 404 w przeglądarce.
źródło
źródło
Być może znajdziesz klejnot pluggable_js jako odpowiednie rozwiązanie.
źródło
LoadJS gem ma innej opcji:
źródło
Odpowiedź Filipa jest całkiem dobra. Oto kod, aby to działało:
W application.html.erb:
<body class="<%=params[:controller].parameterize%>">
Zakładając, że twój kontroler nazywa się Projekty, które wygenerują:
<body class="projects">
Następnie w projects.js.coffee:
źródło
<body>
jest ipso facto nieprawidłowe. Zobacz moje komentarze w innym miejscu na tej stronie.Skrypty JavaScript są scalane tylko wtedy, gdy powiesz Railsom (raczej zębatkom), aby je scaliły.
źródło
//= require_tree .
?require_tree .
jest zwykle złym pomysłem.W ten sposób rozwiązałem problem ze stylizacją: (przepraszam Haml)
W ten sposób uruchamiam wszystkie pliki .css.sass specyficzne dla strony za pomocą:
W ten sposób możesz łatwo uniknąć wszelkich starć. Jeśli chodzi o pliki .js.coffee , możesz po prostu zainicjować elementy takie jak;
Mam nadzieję, że to pomogło niektórym.
źródło
$('#post > #edit') ->
wydaje się być nieważny. Jak zaklasyfikować jQuery do pracy w zakresie?= javascript_include_tag "application"
i w= javascript_include_tag params[:controller]
ten sposób mogę zachować kod JavaScript bez konieczności określania zakresu w pliku.Możesz również pogrupować plik js w folderach i nadal używać potoku zasobów do selektywnego ładowania javascript w zależności od strony.
źródło
Zgadzam się z twoją odpowiedzią, aby sprawdzić, czy ten selektor istnieje, użyj:
(nie widziałem, żeby ktokolwiek dodał rzeczywiste rozwiązanie)
źródło
Nie widzę odpowiedzi, która naprawdę to wszystko łączy i przedstawia dla ciebie. Dlatego postaram się połączyć meleyal , sujal (a la ClosureCowboy ), pierwszą część odpowiedzi Ryana , a nawet śmiałą wypowiedź Gal o Backbone.js ... wszystko razem w sposób krótki i jasny. I kto wie, może nawet spotkam się z Marnen Laibow-Koser .
Przykładowe zmiany
asset / javascripts / application.js
views / layouts / application.html.erb
views / foo / index.html.erb
asset / javascripts / foo.js
asset / javascripts / foostuff / foothis.js.coffee
Krótki opis
Usuń
//= require_tree .
z application.js i wymień tylko JS, które udostępnia każda strona.Dwie linie pokazane powyżej w application.html.erb wskazują stronie, gdzie należy dołączyć application.js i JS specyficzny dla strony.
Trzy wiersze pokazane powyżej w pliku index.html.erb nakazują widokowi wyszukiwanie JS specyficznych dla strony i dołączenie go do nazwanego regionu wydajności o nazwie „: javascript” (lub jakkolwiek chcesz go nazwać). W tym przykładzie kontrolerem jest „foo”, więc Railsy spróbują dołączyć „foo.js” w regionie wydajności: javascript w układzie aplikacji.
Wymień JS specyficzny dla strony w foo.js (lub jakiejkolwiek nazwie kontrolera). Lista wspólnych bibliotek, drzewa, katalogów, cokolwiek.
Zachowaj swój niestandardowy JS specyficzny dla strony w miejscu, w którym możesz łatwo do niego odwoływać, oprócz innych niestandardowych JS. W tym przykładzie foo.js wymaga drzewa foostuff, więc umieść tam swój niestandardowy JS, na przykład foothis.js.coffee .
Tutaj nie ma twardych zasad. W razie potrzeby możesz swobodnie przenosić różne elementy, a może nawet utworzyć wiele obszarów zbiorów o różnych nazwach w różnych układach. To pokazuje tylko jeden możliwy pierwszy krok naprzód. (Nie robię tego dokładnie tak, biorąc pod uwagę nasze użycie Backbone.js. Mógłbym również upuścić foo.js do folderu o nazwie foo zamiast foostuff, ale jeszcze tego nie zdecydowałem).
Notatki
Możesz robić podobne rzeczy za pomocą CSS,
<%= stylesheet_link_tag params[:controller] %>
ale to nie wchodzi w zakres pytania.Jeśli przegapiłem rażącą najlepszą praktykę tutaj, wyślij mi notatkę, a ja dostosuję się do conisder. Rails jest dla mnie dość nowy i, szczerze mówiąc, do tej pory nie jestem pod ogromnym wrażeniem chaosu, który domyślnie wprowadza do rozwoju przedsiębiorstwa i całego ruchu generowanego przez przeciętny program Railsowy.
źródło
Mam inne rozwiązanie, które choć prymitywne działa dla mnie dobrze i nie wymaga żadnych wymyślnych strategii ładowania selektywnego. Włóż funkcję gotowego dokumentu nornal, ale następnie sprawdź bieżącą lokalizację systemu Windows, aby sprawdzić, czy jest to strona, dla której przeznaczony jest javascript:
Nadal pozwala to na załadowanie wszystkich plików JS przez szyny 3.x w jednym małym pakiecie, ale nie generuje dużego obciążenia ani żadnych konfliktów ze stronami, dla których plik JS nie jest przeznaczony.
źródło
Odpowiedź ryguy jest dobrą odpowiedzią, mimo że została oceniona na negatywne.
Zwłaszcza jeśli używasz czegoś takiego jak Backbone JS - każda strona ma swój własny widok Backbone. Następnie plik erb ma tylko jeden wiersz wbudowanego javascript, który uruchamia klasę widoku prawego szkieletu. Uważam to za pojedynczy wiersz „kodu kleju”, a zatem fakt, że jego wstawka jest OK. Zaletą jest to, że możesz zachować „wymagany_tree”, co pozwala przeglądarce na buforowanie całego javascript.
w show.html.erb będziesz mieć coś takiego:
aw pliku układu potrzebujesz:
źródło
Przenieś wszystkie swoje wspólne pliki JS do podfolderu, takiego jak „app / asset / javascript / global”, a następnie w pliku application.js zmień
//= require_tree .
wiersz na//= require_tree ./global
.Teraz możesz umieścić swoją JS specyficzną dla kontrolera w katalogu głównym „app / asset / javascript /” i nie będą one uwzględnione w skompilowanym JS, będą używane tylko wtedy, gdy wywołasz je za pośrednictwem
= javascript_include_tag
kontrolera / widoku.źródło
Chociaż masz tutaj kilka odpowiedzi, myślę, że Twoja edycja jest prawdopodobnie najlepszym wyborem. Wzorzec projektowy, którego używamy w naszym zespole, który otrzymaliśmy od Gitlab, to wzór Dyspozytora. Robi coś podobnego do tego, o czym mówisz, jednak nazwa strony jest ustawiana w tagu body za pomocą szyn. Na przykład w pliku układu po prostu dołącz coś takiego (w HAML):
W takim przypadku masz tylko jedno zamknięcie i instrukcję switch w swoim
dispatcher.js.coffee
pliku w folderze javascripts:Wszystko, co musisz zrobić w poszczególnych plikach (powiedzmy
products.js.coffee
lublogin.js.coffee
na przykład), to umieścić je w klasie, a następnie zglobalizować ten symbol klasy, aby uzyskać do niego dostęp w programie rozsyłającym:Gitlab ma kilka przykładów tego, z którymi możesz się wyśmiewać na wypadek, gdybyś był ciekawy :)
źródło
Projekt Paloma oferuje ciekawe podejście do zarządzania specyficznym dla strony kodem javascript.
Przykład użycia z ich dokumentów:
źródło
Krok 1. usuń wymagane drzewo. w plikach application.js i application.css.
Krok 2. Edytuj plik application.html.erb (domyślnie w szynach) w folderze układu. Dodaj „params [: kontroler]” w następujących tagach.
Krok 3. Dodaj plik w config / initializers / resources.rb
referencje: http://theflyingdeveloper.com/controller-specific-assets-with-rails-4/
źródło
Nie wypróbowałem tego, ale wygląda na to, że spełnione są następujące warunki:
jeśli masz content_for, czyli javascript (np. z prawdziwym javascript w nim zawartym), koła zębate nie wiedziałyby o tym, a zatem działałoby to tak samo jak teraz.
jeśli chcesz wykluczyć plik z dużego pakietu javascript, przejdź do pliku config / sprockets.yml i odpowiednio zmodyfikuj pliki_źródłowe. Następnie wystarczy w razie potrzeby dołączyć dowolny plik, który został wykluczony.
źródło
Zrobiłem to wcześniej przy użyciu tej metody: http://theflyingdeveloper.com/controller-specific-assets-with-rails-4/ . Super-łatwe, polega na kontrolerach, aby wybrać odpowiedni plik js do załadowania.
źródło
Połączyłem niektóre odpowiedzi w:
Pomocnik aplikacji:
layouts / application.html.haml:
źródło
Po pierwsze: usuń
\\=require_tree
z application.js Po drugie: cały twój kod JS musi być przydzielony na,/app/assets/javascritpt
a cały twój kod CSS musi być przydzielony na/app/assets/stylesheets
źródło
Idąc tropem Ryana, oto co zrobiłem-
application.js.coffee
users.js.coffee (coffeescript specyficzny dla kontrolera, np. kontroler: użytkownicy, akcja: pulpit nawigacyjny)
application.html.haml
źródło
eval
), jeśli Twój HTML zostanie naruszony przez pęknięty serwer lub złośliwy skrypt użytkownika.Oto jak to zrobić, zwłaszcza jeśli nie musisz uruchamiać ton bibliotek dla określonej strony, ale tylko uruchomić kilkaset wierszy JS mniej więcej.
Ponieważ osadzanie kodu JavaScript w HTML jest całkowicie w porządku, po prostu stwórz w katalogu app / views shared.js i umieść tam swój kod strony / stron wewnątrz my_cool_partial.html.erb
Teraz z dowolnego miejsca po prostu rób:
I to wszystko, k?
źródło