Как сделать постраничный JavaScript с конвейером ресурсов Rails - PullRequest
14 голосов
/ 23 января 2012

Я понимаю, что по соображениям производительности лучше позволить конвейеру активов объединить и минимизировать весь мой javascript и отправлять весь лот с каждым запросом страницы. Это достаточно справедливо

Однако, мой javascript - это такие вещи, как привязка определенного поведения к конкретным элементам страницы - например,

$('button').click(function(e) { $('input.sel').val(this.name); }

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

Я бы предпочел не помещать весь этот материал встроенным в элементы, просто потому, что когда он становится длиннее двух строк, правильно корректировать отступ javascript внутри файла .html.erb - это больше работы, чем нужно

Ответы [ 5 ]

17 голосов
/ 23 января 2012

Вот что я делаю (основываясь на некоторых ответах от stackoverflow):

application_helper.rb

def body_page_name
  [controller_name.classify.pluralize, action_name.classify].join
end

application.html.haml

  %body{data: {page: body_page_name}}

application.js

$(function() {
  var page = $("body").data("page");
  if("object" === typeof window[page])
    window[page].init();
});

И в соответствующем js-файле есть объект с именем ControllerAction:

tickets.js

var TicketsShow = new function() {
  var self = this;

  self.init = function() {
    // code which may call other functions in self
  };
};

Возможно, есть лучший способ сделать это, но это работаетдля меня

4 голосов
/ 23 января 2012

Я опишу то, что я сейчас делаю, на всякий случай, если кто-нибудь получит лучшую идею

1) Я изменил тег body в моем application.html.erb, чтобы добавить текущий контроллер и действие в качестве атрибутов данных

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

2) Я проверяю это в верхней части соответствующего JavaScript

$(document).ready(function() {
        if($('body').data('controller')=='stories') {
            $('.story').click(function(e) {
                    var u=$(this).data('url');
                    u && (document.location=u);
            });
        }
    });

Я не могу решить, считаю ли я это хорошей идеей или нет

1 голос
/ 17 марта 2014

Для JavaScript для конкретной страницы я обычно делаю что-то вроде этого:

Приложение Helper

В помощнике приложения я создаю атрибут класса (хотя вы также можете использовать атрибут данных).

module ApplicationHelper
  def body_attributes
    controller = params[:controller].gsub('/', ' ')
    action = params[:action]
    version = @version ? "version_#{@version}" : nil
    {
      class: ([controller, action, version] - [nil]).join(' ')
    }
  end
end

Примечание. Я также добавляю строку версии. Это помогает в экспериментах с контентом Google и упрощает A / B-тестирование.

Application.html.haml

В моем глобальном файле макета я делаю что-то вроде этого, чтобы вставить атрибуты в тег body:

!!! 5
%html
  %head
    ...
  %body{body_attributes}

script.js

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

$(function () {
  if ($('body.pledge.new, body.pledge.create').length > 0) {
    // do work here...
  }
});

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

EDIT

Обратите внимание, что этому ответу уже 3 года. Вместо этого вы должны использовать клиентскую маршрутизацию с такой инфраструктурой, как React.

0 голосов
/ 23 января 2012

Я сделал это и видел, как это делалось несколькими способами:

  1. Оснащение mvc для возможности загрузки определенного js-файла на страницу, названного по тем же строкам, что и файл контроллера. Нравится: <controller-name>.js

  2. Создание анализатора URL в JS, а затем установка глобальной переменной для текущей страницы: UrlParams.currentView = 'dashboard';, а затем произнесение if(UrlParams.currentView == 'dashboard') { //do specific js here }

  3. Установка уникального идентификатора в качестве класса страницы или идентификатора, а затем нацеливание на него с помощью селекторов JS. $('#dashboard').xyz();

0 голосов
/ 23 января 2012

Я бы добавил класс к тегу BODY, позволяющий идентифицировать каждую страницу и, следовательно, каждый элемент управления на странице.

<body class='page1'>

JS:

$('.page1 button').click(function(e) { $('input.sel').val(this.name); }
...