Используя Rails 3.1, куда вы помещаете свой «специфичный для страницы» код JavaScript?

376

Насколько я понимаю, весь ваш javascript объединяется в 1 файл. Rails делает это по умолчанию, когда добавляет //= require_tree . в конец файла манифеста application.js.

Это похоже на реальную экономию жизни, но меня немного беспокоит код javascript, специфичный для страницы. Выполняется ли этот код на каждой странице? Последнее, что я хочу, - это создание всех объектов для каждой страницы, когда они нужны только на 1 странице.

Кроме того, не существует ли потенциал для кода, который тоже сталкивается?

Или вы помещаете небольшой тег script в нижней части страницы, который просто вызывает метод, который выполняет код javascript для страницы?

Вам больше не нужно require.js?

Спасибо

EDIT: Я ценю все ответы... и я не думаю, что они действительно попадают в проблему. Некоторые из них касаются стиля и, похоже, не связаны друг с другом... и другие просто упоминают javascript_include_tag..., которые, как я знаю, существуют (очевидно...), но казалось бы, что путь Rails 3.1 в будущем все ваши Javascript в 1 файл, а не загружать отдельные Javascript в нижней части каждой страницы.

Лучшее решение, которое я могу придумать, - обернуть некоторые функции в теги div с помощью id или class es. В коде javascript вы просто проверяете, есть ли на странице id или class, и если это так, вы запускаете связанный с ним код javascript. Таким образом, если динамический элемент отсутствует на странице, код javascript не запускается - хотя он был включен в массивный файл application.js, упакованный Sprockets.

Мое выше решение имеет то преимущество, что если окно поиска включено на 8 из 100 страниц, оно будет работать только на этих 8 страницах. Вам также не придется включать тот же код на 8 страницах сайта. Фактически, вам никогда не придется включать ручные теги script на ваш сайт где-либо еще раз.

Я думаю, что это фактический ответ на мой вопрос.

  • 10
    «Путь Rails 3.1 в будущем заключается в том, чтобы обернуть весь ваш Javascript в 1 файл, а не загружать отдельный Javascript внизу каждой страницы.» - Только потому, что основная команда Rails плохо знает, как управлять JavaScript. Небольшие файлы, как правило, лучше (см. Мои комментарии в другом месте). Когда дело доходит до JavaScript, путь Rails редко бывает правильным (за исключением конвейера ресурсов, который пинает задницу и поощряет CoffeeScript).
  • 0
    Таким образом, вы будете включать свои js-файлы для каждой страницы на каждой странице? Я думаю, что это пустая трата времени, я больше согласен с ответом ClosureCowboy.
Показать ещё 12 комментариев
Теги:
asset-pipeline
sprockets
ruby-on-rails-3.1

28 ответов

22
Лучший ответ

Я ценю все ответы... и я не думаю, что они действительно попадают в проблему. Некоторые из них касаются стилизации и, похоже, не связаны друг с другом... и другие просто упоминают javascript_include_tag..., которые, как я знаю, существуют (очевидно...), но, похоже, что путь Rails 3.1 в будущем все ваши Javascript в 1 файл, а не загружать отдельные Javascript в нижней части каждой страницы.

Лучшее решение, которое я могу придумать, - это обернуть некоторые функции в тегах div с помощью id или class es. В коде javascript. Затем вы просто проверяете, находится ли на странице id или class, и если это так, вы запускаете код javascript, который связан с ним. Таким образом, если динамический элемент отсутствует на странице, код javascript не запускается - хотя он был включен в массивный файл application.js, упакованный Sprockets.

Мое выше решение имеет то преимущество, что если окно поиска включено на 8 из 100 страниц, оно будет работать только на этих 8 страницах. Вам также не придется включать тот же код на 8 страницах сайта. Фактически, вам никогда не придется включать ручные теги script на вашем сайте где-либо еще раз - за исключением, возможно, предварительной загрузки данных.

Я думаю, что это фактический ответ на мой вопрос.

  • 0
    Но на самом деле вам нужны эти ручные теги <script> . Да, классы и идентификаторы являются частью ответа, но для пользователя нет смысла загружать JavaScript, который не требуется для этой конкретной страницы.
  • 4
    @ MarnenLaibow-Koser причина, по которой вы не добавляете теги сценариев вручную на каждую уникальную страницу, заключается в том, что вы должны загружать содержимое сценария при каждом просмотре страницы. Если вы можете упаковать весь javascript в application.js с помощью конвейера ресурсов, то пользователь загружает эти сценарии только один раз и извлекает application.js из кэша при всех последующих загрузках страницы.
Показать ещё 12 комментариев
158

Документы Asset Pipeline предлагают, как выполнять специфичные для контроллера JS:

Например, если создается ProjectsController, в app/assets/javascripts/projects.js.coffee будет новый файл, а другой - в app/assets/stylesheets/projects.css.scss. Вы должны поместить любой JavaScript или CSS, уникальный для контроллера внутри своих соответствующих файлов активов, так как эти файлы затем могут быть загружены только для этих контроллеров с такими строками, как <%= javascript_include_tag params[:controller] %> или <%= stylesheet_link_tag params[:controller] %>.

Ссылка на: asset_pipeline

  • 50
    Это самый элегантный способ сделать это. Но вам также нужно удалить строку // = require_tree. из приложения .js.coffee
  • 2
    Я полностью согласен с этим методом. Другие методы кажутся очень неуклюжими и все же заканчивают тем, что загружали гигантский файл js. Проект, над которым я работаю, содержит почти 2 МБ файлов / плагинов и т. Д. ПОСЛЕ объединения / минимизации.
Показать ещё 7 комментариев
74

Для конкретного js страницы вы можете использовать Garber-Irish solution.

Итак, ваша папка javascripts Rails может выглядеть так для двух контроллеров - автомобилей и пользователей:

javascripts/
├── application.js
├── init.js
├── markup_based_js_execution
├── cars
│   ├── init .js
│   ├── index.js
│   └── ...
└── users
    └── ...

И javascripts будет выглядеть так:

// application.js

//= 
//= require init.js
//= require_tree cars
//= require_tree users

// init.js

SITENAME = new Object();
SITENAME.cars = new Object;
SITENAME.users = new Object;

SITENAME.common.init = function (){
  // Your js code for all pages here
}

// cars/init.js

SITENAME.cars.init = function (){
  // Your js code for the cars controller here
}

// cars/index.js

SITENAME.cars.index = function (){
  // Your js code for the index method of the cars controller
}

и markup_based_js_execution будет содержать код для объекта UTIL и выполнение DOM-ready UTIL.init.

И не забудьте поместить это в свой файл макета:

<body data-controller="<%= controller_name %>" data-action="<%= action_name %>">

Я также думаю, что лучше использовать классы вместо атрибутов data-*, для лучшего CSS-страницы. Как сказал Джейсон Гарбер: специальные CSS-селектора страниц могут стать очень неудобными (при использовании атрибутов data-*)

Надеюсь, это поможет вам.

  • 4
    Что если вам нужна переменная, доступная для всех действий в контроллере пользователя, но недоступная в других контроллерах? Разве у этого метода нет проблем с областью видимости?
  • 0
    @ tybro0103, я думаю, что для реализации этого поведения вы хотели бы написать что-то вроде window.varForOneController='val' в этой функции инициализации контроллера. Также здесь может помочь Gon Gem ( github.com/gazay/gon ). Могут быть и другие обходные пути.
Показать ещё 18 комментариев
68

Я вижу, что вы ответили на свой вопрос, но вот еще один вариант:

В принципе, вы делаете предположение, что

//= require_tree .

. Не это. Не стесняйтесь удалять его. В моем текущем приложении первое, что я делаю с 3.1.x честно, я сделал три разных JS файла верхнего уровня. Мой файл application.js имеет

//= require jquery
//= require jquery_ujs
//= require_directory .
//= require_directory ./api
//= require_directory ./admin

Таким образом, я могу создавать подкаталоги со своими собственными файлами JS верхнего уровня, которые включают только то, что мне нужно.

Ключами являются:

  • Вы можете удалить require_tree - Rails позволяет изменять сделанные им предположения.
  • Нет ничего особенного в имени application.js - любой файл в подкаталоге assets/javascript может включать в себя предпроцессорные директивы с //=

Надеюсь, что это поможет и добавляет некоторые детали ответа ClosureCowboy.

Sujal

  • 8
    +1 Это здорово знать для новичка, как я. Я бы дал +2, если бы мог.
  • 5
    @sujal Точно. Основная команда Rails славится ужасным управлением JavaScript. Не стесняйтесь игнорировать их предложения и просто использовать хорошие части конвейера активов. :)
Показать ещё 2 комментария
40

Еще одна опция: для создания файлов, зависящих от страницы или модели, вы можете создавать каталоги внутри вашей папки assets/javascripts/.

assets/javascripts/global/
assets/javascripts/cupcakes
assets/javascripts/something_else_specific

Ваш основной файл манифеста application.js можно настроить для загрузки его файлов из global/. Конкретные страницы или группы страниц могут иметь свои собственные манифесты, которые загружают файлы из своих конкретных каталогов. Звездочки будут автоматически комбинировать файлы, загруженные application.js, с вашими файлами, зависящими от страницы, что позволяет этому решению работать.

Этот метод можно использовать и для style_sheets/.

  • 0
    приятно знать ; ) Спасибо.
  • 13
    Вы заставили меня жаждать кексы сейчас .. Dangit!
Показать ещё 5 комментариев
16

Я понимаю, что я прихожу на эту вечеринку немного поздно, но я хотел бросить решение, которое я использовал в последнее время. Однако позвольте мне сначала упомянуть...

Rails 3.1/3.2 Way (Нет, сэр. Мне это не нравится.)

Смотрите: http://guides.rubyonrails.org/asset_pipeline.html#how-to-use-the-asset-pipeline

Я включаю следующее для полноты в этом ответе и потому, что это не является нежизнеспособным решением... хотя мне все равно.

"Rails Way" - это ориентированное на контроллер решение, а не ориентированное на просмотр, как того требует первоначальный автор этого вопроса. Существуют JS файлы, специфичные для контроллера, названные в честь их соответствующих контроллеров. Все эти файлы помещаются в дерево папок, которое по умолчанию не включено ни в одну из директив application.js.

Чтобы включить код, специфичный для контроллера, к представлению добавляется следующее.

<%= javascript_include_tag params[:controller] %>

Я ненавижу это решение, но оно там и так быстро. Предположительно, вы можете вместо этого называть эти файлы чем-то вроде "people-index.js" и "people-show.js", а затем использовать что-то вроде "#{params[:controller]}-index" для получения ориентированного на представление решения. Опять же, быстро исправить, но это не очень хорошо со мной.

Мой путь к атрибутам данных

Назовите меня сумасшедшим, но я хочу, чтобы весь мой JS был скомпилирован и переназначен в application.js при развертывании. Я не хочу забывать включать эти маленькие файлы отставших повсюду.

Я загружаю все мои JS в один компактный, скоро будущий браузер кешированный файл. Если определенную часть моего приложения .js нужно уволить на странице, я позволяю HTML-сообщению мне, а не Rails.

Вместо того, чтобы блокировать мой JS для определенных идентификаторов элементов или мешать моему HTML классам маркеров, я использую атрибут пользовательских данных, называемый data-jstags.

<input name="search" data-jstag="auto-suggest hint" />

На каждой странице я использую - вставляю предпочтительный метод библиотеки JS здесь - для запуска кода, когда DOM закончил загрузку. Этот код начальной загрузки выполняет следующие действия:

  • Итерации по всем элементам в DOM, помеченным data-jstag
  • Для каждого элемента разделите значение атрибута на пробел, создав массив строк тегов.
  • Для каждой строки тега выполните поиск в Hash для этого тега.
  • Если найден подходящий ключ, запустите связанную с ним функцию, передав элемент в качестве параметра.

Так что скажите, что у меня есть следующее определение в моем приложении application.js:

function my_autosuggest_init(element) {
  /* Add events to watch input and make suggestions... */
}

function my_hint_init(element) {
  /* Add events to show a hint on change/blur when blank... */
  /* Yes, I know HTML 5 can do this natively with attributes. */
}

var JSTags = {
  'auto-suggest': my_autosuggest_init,
  'hint': my_hint_init
};

Событие начальной загрузки будет применять функции my_autosuggest_init и my_hint_init к поисковому вводу, превратив его в вход, который отображает список предложений во время ввода пользователем, а также предоставляет подсказки для ввода, когда вход остается пустым и не сфокусированным.

Если какой-либо элемент отмечен data-jstag="auto-suggest", код автоматического предложения никогда не срабатывает. Тем не менее, он всегда там, минимизирован и в конечном итоге кэшируется в моем приложении application.js для тех времен, которые мне нужны на странице.

Если вам нужно передать дополнительные параметры вашим меченым функциям JS, вам придется применить некоторые креативы. Либо добавьте атрибуты параметров данных, придумайте какой-то синтаксис параметров, либо даже используйте гибридный подход.

Даже если у меня есть сложный рабочий процесс, который кажется специфичным для контроллера, я просто создам файл для него в моей папке lib, упакую его в application.js и пометьте его чем-то вроде "мастера новых вещей". Когда мой загрузочный диск попадает в этот тег, мой красивый, причудливый мастер будет создан и запущен. Он запускается для этого вида (ов) контроллера, когда это необходимо, но не подключается к контроллеру иначе. На самом деле, если я правильно закодирую свой мастер, я могу предоставить все данные конфигурации в представлениях и, следовательно, иметь возможность повторно использовать мой мастер позже для любого другого контроллера, который в нем нуждается.

Во всяком случае, именно так я уже некоторое время внедряю JS для конкретных страниц, и он отлично зарекомендовал себя как для простых дизайнов сайтов, так и для более сложных/богатых приложений. Надеюсь, одно из двух решений, которые я представил здесь, мой путь или путь Rails, полезно для всех, кто сталкивается с этим вопросом в будущем.

  • 6
    Одна маленькая деталь: в вашем ответе есть понятие, что после того, как js будет кеширован браузером, это не повлияет. Это не совсем так. Браузер действительно избегает загрузки, если файл js правильно кэшируется, но все равно компилирует код при каждом отображении страницы. Таким образом, вы должны сбалансировать компромиссы. Если у вас много JS в совокупности, но только одна используется на страницу, вы можете улучшить время страницы, разбив JS на части.
  • 0
    Более подробно о практических эффектах этого этапа компиляции, о котором я говорю, см. Объяснение 37 сигналов о том, как pjax повлиял на Basecamp. Далее: 37signals.com/svn/posts/…
Показать ещё 4 комментария
7

На это были даны ответы и приняты давно, но я придумал свое решение на основе некоторых из этих ответов и моего опыта работы с Rails 3 +.

Конвейер активов сладкий. Используйте его.

Сначала в файле application.js удалите //= require_tree.

Затем в вашем application_controller.rb создайте вспомогательный метод:

helper_method :javascript_include_view_js //Or something similar

def javascript_include_view_js
    if FileTest.exists? "app/assets/javascripts/"+params[:controller]+"/"+params[:action]+".js.erb"
        return '<script src="/assets/'+params[:controller]+'/'+params[:action]+'.js.erb" type="text/javascript"></script>'
    end
end

Затем в вашем макете application.html.erb добавьте новый помощник из существующих javascript-включений, с префиксом raw helper:

<head>
    <title>Your Application</title>
    <%= stylesheet_link_tag "application", :media => "all" %>
    <%= javascript_include_tag "application" %>
    <%= raw javascript_include_view_js %>
</head>

Voila, теперь вы можете легко создавать javascript с конкретным видом, используя ту же файловую структуру, которую вы используете везде в рельсах. Просто вставьте свои файлы в app/assets/:namespace/:controller/action.js.erb!

Надеюсь, что это поможет кому-то еще!

  • 1
    Разве это не вызывает проблемы после того, как ресурсы предварительно скомпилированы и во время выполнения <%= raw ... %> вернет 404?
  • 0
    Я думаю, что конвейер ресурсов не приятен, так как он создает кучу файлов, которые часто не должны использоваться. Поэтому для меня опора на конвейер активов создает зависимость от неэффективной системы.
Показать ещё 1 комментарий
6

Возможно, вы найдете pluggable_js gem в качестве подходящего решения.

  • 2
    На мой взгляд, это лучшее решение.
6
<%= javascript_include_tag params[:controller] %>
  • 2
    Похоже, что сможет ответить на вопрос. Не могли бы вы добавить больше к ответу, чтобы уточнить это?
6

Вы можете добавить эту строку в свой файл макета (например, application.html.erb), чтобы автоматически загружать специфический для контроллера файл javascript (тот, который был создан при создании контроллера):

<%= javascript_include_tag params[:controller] %>

Вы также можете добавить строку для автоматической загрузки файла script в рамках каждого действия.

<%= javascript_include_tag params[:controller] + "/" + params[:action] %>

Просто поместите свои скрипты страниц в поддиректорию, названную по имени контроллера. В эти файлы вы можете включить другие скрипты, используя = require. Было бы неплохо создать помощник, чтобы включить файл только в том случае, если он существует, чтобы избежать ошибки 404 в браузере.

5

LoadJS gem - еще один вариант:

LoadJS обеспечивает способ загрузки специфичного для JavaScript кода JavaScript в приложении Rails без потери магии, предоставляемой Sprockets. Весь ваш Javascript-код будет продолжен, как минимум, в одном файле Javascript, но некоторые его части будут выполняться только для определенных страниц.

https://github.com/guidomb/loadjs

3

Ответ Филиппа неплохой. Вот код, чтобы заставить его работать:

В application.html.erb:

<body class="<%=params[:controller].parameterize%>">

Предполагая, что ваш контроллер называется Projects, который будет генерировать:

<body class="projects">

Затем в projects.js.coffee:

jQuery ->
  if $('body.projects').length > 0  
     $('h1').click ->
       alert 'you clicked on an h1 in Projects'
  • 0
    Даунтинг: любое решение, которое помещает класс в <body> является ipso facto некорректным. Смотрите мои комментарии в другом месте на этой странице.
  • 0
    Не делай этого. Эта проблема заключается в том, что каждый раз, когда вы добавляете один из них, вы добавляете другой фрагмент js, который должен выполняться при загрузке страницы. Определенно может привести к некоторому снижению производительности по мере роста вашего проекта.
2

Я не вижу ответа, который действительно ставит все это вместе и выдает вам. Таким образом, я постараюсь поставить meleyal, sujal (a la ClosureCowboy), первую часть ответа Райана, и даже смелое выражение Гала о Backbone.js... все вместе так коротким и ясным. И, кто знает, я мог бы даже встретить требования Марнена Лайбоу-Косера.

Примеры изменений

активы/JavaScripts/ application.js

//= require jquery
//= require jquery_ujs
//= require lodash.underscore.min
...


просмотров/макеты/ application.html.erb

  ...
  </footer>

  <!-- Javascripts ================================================== -->
  <!-- Placed at the end of the document so the pages load faster -->
  <%= javascript_include_tag "application" %>
  <%= yield :javascript %>

</body>
</html>


просмотров /Foo/ index.html.erb

...
<% content_for :javascript do %>
  <%= javascript_include_tag params[:controller] %>
<% end %>


активы /JavaScripts/ foo.js

//= require moment
//= require_tree ./foostuff


активы /JavaScripts/foostuff/ foothis.js.coffee

alert "Hello world!"


Краткое описание

  • Удалите //= require_tree . из application.js и перечислите только JS, который разделяет каждая страница.

  • Две строки, показанные выше в application.html.erb, указывают страницу, на которой должны быть указаны application.js и JS вашей страницы.

  • Три строки, показанные выше в index.html.erb, указывают вашему представлению на поиск конкретной JS-страницы и включают ее в область имен с именем ": javascript" (или все, что вы хотите назвать). В этом примере контроллер "foo", поэтому Rails будет пытаться включить "foo.js" в область yield: javascript в макете приложения.

  • Перечислите JS с вашей страницы в foo.js (или независимо от имени контроллера). Перечислите общие библиотеки, дерево, каталоги, что угодно.

  • Храните свой собственный JS-код на странице, где вы можете легко ссылаться на него отдельно от другой пользовательской JS. В этом примере foo.js требует, чтобы дерево foostuff размещало ваш собственный JS, например foothis.js.coffee.

  • Здесь нет жестких правил. Не стесняйтесь перемещать вещи и, возможно, даже создавать несколько областей дохода различных имен в различных макетах, если это необходимо. Это просто показывает первый возможный шаг вперед. (Я не делаю этого точно так же, как при использовании Backbone.js. Возможно, я также захочу удалить foo.js в папку с именем foo вместо foostuff, но пока не решил.)

Примечания

Вы можете делать похожие вещи с CSS и <%= stylesheet_link_tag params[:controller] %>, но это выходит за рамки вопроса.

Если я пропустил вопиющую передовую практику, отправьте мне записку, и я соглашусь адаптироваться. Rails для меня довольно новичок, и, честно говоря, я пока не впечатлен тем, что хаос, который он по умолчанию использует для развития предприятия, и весь трафик, который генерирует средняя программа Rails.

  • 0
    это похоже на путь, я собираюсь посмотреть, смогу ли я реализовать его в своем собственном приложении, спасибо за подробный ответ.
2

Вы также можете группировать js в папках и продолжать использовать конвейер ресурсов для выборочно загружать javascript в зависимости от страницы.

2

Я согласен с вашим ответом, чтобы проверить, есть ли этот селектор, используйте:

if ($(selector).length) {
    // Put the function that does not need to be executed every page
}

(не видел, чтобы кто-нибудь добавлял фактическое решение)

2

Вот как я решил проблему стилизации: (извините Haml)

%div{:id => "#{params[:controller].parameterize} #{params[:view]}"}
    = yield

Таким образом, я запускаю все страницы .css.sass с помощью

#post
  /* Controller specific code here */
  &#index
    /* View specific code here */
  &#new
  &#edit
  &#show

Таким образом, вы можете легко избежать любых столкновений. Когда дело доходит до файлов .js.coffee, вы можете просто инициализировать такие элементы, как:

$('#post > #edit') ->
  $('form > h1').css('float', 'right')

Надеюсь, это помогло кому-то.

  • 0
    Вопрос стайлинга? А? Я не спрашивал о CSS ...
  • 1
    Прочитайте последний бит еще раз, пожалуйста, для javascript вы можете воспользоваться той же структурой, которая используется для таблиц стилей для инициализации определенных функций представления.
Показать ещё 2 комментария
2

JavaScripts объединяются только тогда, когда вы указываете Rails (Sprockets, скорее), чтобы объединить их.

  • 0
    Конечно. Наверное, я спрашиваю, потому что по умолчанию в Rails есть все в папке ... что означает, что Дэвид намерен сделать это для вас. Но, как я сказал в другом комментарии к @rubyprince, я не уверен насчет выполнения, когда это делается таким образом. Я думаю, что я должен отключить //= require_tree . ?
  • 0
    @FireEmblem Да. require_tree . обычно плохая идея.
1

Шаг1. Удалите require_tree. в ваших приложениях .js и application.css.

Step2. Измените файл application.html.erb(по умолчанию rails) в папке макета. Добавьте "params [: controller]" в следующие теги.

<%= stylesheet_link_tag    'application', params[:controller], media: 'all', 'data-turbolinks-track' => true %>

<%= javascript_include_tag 'application', params[:controller], 'data-turbolinks-track' => true %>

Step3. Добавить файл в config/initializers/assets.rb

%w( controller_one controller_two controller_three ).each do |controller|
  Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.js.coffee", "#{controller}.css", "#{controller}.scss"]
end

ссылки: http://theflyingdeveloper.com/controller-specific-assets-with-rails-4/

  • 0
    Хотя это может теоретически ответить на вопрос, было бы предпочтительным включить сюда основные части ответа и предоставить ссылку для справки.
1

Paloma проект предлагает интересный подход для управления конкретным JavaScript-кодом страницы.

Пример использования из своих документов:

var UsersController = Paloma.controller('Users');

// Executes when Rails User#new is executed.
UsersController.prototype.new = function(){
   alert('Hello Sexy User!' );
};
1

Хотя у вас есть несколько ответов здесь, я думаю, что ваше редактирование, вероятно, лучший выбор. Шаблон дизайна, который мы используем в нашей команде, который мы получили из Gitlab, - это шаблон Диспетчера. Он делает что-то похожее на то, о чем вы говорите, однако имя страницы устанавливается в теге body рельсами. Например, в вашем файле макета просто включите что-то вроде (в HAML):

%body{'data-page' => "#{controller}:#{action}" }

Тогда в вашем файле dispatcher.js.coffee в вашем каталоге javascripts будет только одно закрытие и инструкция switch в следующем виде:

$ ->
  new Dispatcher()

class Dispatcher
  constructor: ->
    page = $('body').attr('data-page')
    switch page
      when 'products:index'
        new Products() 
      when 'users:login'
        new Login()

Все, что вам нужно сделать в отдельных файлах (например, products.js.coffee или login.js.coffee), заключает их в класс и затем глобализует этот символ класса, чтобы вы могли получить доступ к нему в диспетчере:

class Products
  constructor: ->
    #do stuff
@Products = Products

В Gitlab есть несколько примеров этого, которые вы можете захотеть сокрушить, если вам интересно:)

1

Переместите все ваши JOM файлы commom в подпапку, например "app/assets/javascript/global", а затем в application.js, измените строку //= require_tree . на //= require_tree ./global.

Теперь вы можете поместить свой JS-контроллер в корневой каталог "app/assets/javascript/", и они не будут включены в скомпилированный JS, который используется, когда вы вызываете их через = javascript_include_tag на вашем контроллере/вид.

  • 0
    Нет, это дерьмо из JavaScript для загрузки на одну страницу. Даже не имеет значения, если он кешируется.
1

Ответ на ryguy - хороший ответ, хотя он был опущен в отрицательные точки земли.

Особенно, если вы используете что-то вроде Backbone JS - каждая страница имеет собственный вид Backbone. Затем в файле erb есть только одна строка встроенного javascript, который запускает правый класс представления. Я считаю это единственной строкой "кода клея" и, следовательно, тот факт, что его встроенный код в порядке. Преимущество заключается в том, что вы можете сохранить свой "require_tree", который позволяет браузеру кэшировать все javascript.

в show.html.erb, у вас будет что-то вроде:

<% provide :javascript do %>
  <%= javascript_include_tag do %>
    (new app.views.ProjectsView({el: 'body'})).render();
  <% end %>
<% end do %>

и в вашем файле макета вам понадобятся:

<%= yield :javascript %>
  • 0
    Downvoting. Встроенный JavaScript никогда не бывает хорошей идеей. Даже если это клейкий код, он должен быть во внешнем файле.
1

У меня есть другое решение, которое, хотя примитивный работает отлично для меня и не нуждается в каких-либо фантастических стратегий выборочной загрузки. Поместите в свою законченную функцию документа, но затем проверьте текущее местоположение окна, чтобы увидеть, является ли это страница, на которой предназначен ваш javascript:

$(document).ready(function() {
   if(window.location.pathname.indexOf('/yourpage') != -1) {
          // the javascript you want to execute
   }
}

Это все еще позволяет загружать js с помощью rails 3.x в один небольшой пакет, но не создает больших накладных расходов или конфликтов со страницами, для которых js не предназначен.

0

Я собрал несколько ответов на:

Помощник приложения:

module ApplicationHelper
  def js_page_specific_include
    page_specific_js = params[:controller] + '_' + params[:action]
    if Rails.application.assets.find_asset(page_specific_js).nil?
      javascript_include_tag 'application', 'data-turbolinks-track' => true
    else
      javascript_include_tag 'application', page_specific_js, 'data-turbolinks-track' => true
    end
  end
end

Макеты/application.html.haml:

 <!DOCTYPE html>
%html{lang: 'uk'}
  %head   
    = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
   bla-bla-bla
    = js_page_specific_include   
   bla-bla-bla  
0

Ранее я использовал этот метод: http://theflyingdeveloper.com/controller-specific-assets-with-rails-4/. Super-easy, полагается на контроллеры, чтобы выбрать подходящие js для загрузки.

0

Я не пробовал это, но выглядит так:

  • если у вас есть content_for это javascript (например, с реальным javascript внутри него), звездочки не будут знать об этом, и, следовательно, это будет работать так же, как и сейчас.

  • Если вы хотите исключить файл из большого пакета javascript, вы должны войти в файл config/sprockets.yml и соответственно изменить исходные файлы. Затем вы просто включите любой из файлов, которые вы исключили там, где это необходимо.

  • 0
    Является ли исключение файлов или использование собственного javascript на самой странице "правильным способом"? Это то, как Давид хотел, чтобы люди использовали это?
  • 0
    @FireEmblem Мне не важно, что задумал Дэвид, потому что я не думаю, что Дэвид понимает, как правильно организовать JavaScript.
-1

Следуя примеру Райана, вот что я сделал -

application.js.coffee

$ ->
    view_method_name = $("body").data("view") + "_onload"
    eval("#{view_method_name}()") if eval("typeof #{view_method_name} == 'function'")
    view_action_method_name = $("body").data("view") + "_"+$("body").data("action")+"_onload"
    eval("#{view_action_method_name}()") if eval("typeof #{view_action_method_name} == 'function'")

users.js.coffee(конкретный диспетчерский кофейник, например, контроллер: пользователи, действие: панель инструментов)

window.users_dashboard_onload = () ->
    alert("controller action called")
window.users_onload = () ->
    alert("controller called")

application.html.haml

%body{:data=>{:view=>controller.controller_name, :action=>controller.action_name}}
  • 0
    Downvoting. Это смехотворно запутанно - не говоря уже о небезопасности (из-за eval ), если ваш HTML-код скомпрометирован взломанным сервером или вредоносным скриптом пользователя.
-2

Здесь, как это сделать, особенно если вам не нужно выполнять тонны библиотек для вашей конкретной страницы, но только для запуска нескольких сотен строк JS более или менее.

Так как это прекрасно, чтобы вставлять Javascript-код в HTML, просто создайте в каталоге приложения /views shared.js и разместите там свой код страницы/страниц внутри my_cool_partial.html.erb

<script type="text/javascript"> 
<!--
  var your_code_goes_here = 0;
  function etc() {
     ...
  }
-->
</script>

Итак, теперь, где бы вы ни хотели, просто:

  = render :partial => 'shared.js/my_cool_partial'

И что это, k?

  • 2
    Downvoting. Встроенный JavaScript никогда не рекомендуется. HTML должен содержать только разметку. JS и CSS должны быть в отдельных, повторно используемых файлах.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню