Как избежать синтаксического анализа javascript до определения символа?

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

Однако не все символы всегда определены в модели DOM. Например,

$(document).ready(function () {    
    $('#storyCarousel').carousel({
        interval: 3500
    });
});

работает только когда

<div id = "storyCarousel" class = "carousel slide">

определяется в html-части. При загрузке того же javascript с другим html возникает ошибка. В нем говорится, что метод «карусель» не определен: jquery3.self-5af507e…74ad.js?body=1:3819 jQuery.Deferred exception: $(...).carousel is not a function TypeError: $(...).carousel is not a functionРедактировать: @RoryMcCrossan указал, что ошибка не зависит от определения <div id = "storyCarousel" class = "carousel slide"> или нет. Действительно, для этой конкретной проблемы (установка интервала) js не требуется, это можно сделать с помощью атрибута, см. Как изменить интервал времени на загрузочной карусели?

Чтобы удалить ошибку, я попробовал этот трюк, чтобы загрузить специфичный для страницы javascript. Это сводится к

$(document).ready(function () {    
    $(".page.specific").ready(function () {
        $('#storyCarousel').carousel({
          interval: 3500
        });
    });
});

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

Кажется, что гораздо более простой подход состоит в том, чтобы поместить javascript в файл html, который определяет идентификатор:

  <div id = "storyCarousel" class = "carousel slide">
    <!-- Carousel items ... -->

    <script>
      $('#storyCarousel').carousel({
        interval: 3500
      });
    </script>
  </div>

Однако многие люди, похоже, согласны с тем, что HTML и javascript следует хранить отдельно.

Каково общее решение этой проблемы? В чем может быть причина вызова ready ()? Это просто синтаксический анализатор, который уже пытается оценить параметры для ready (), хотя он еще не вызван?

🤔 А знаете ли вы, что...
С помощью JavaScript можно создавать клиентские приложения для мобильных устройств с использованием фреймворков, таких как React Native и NativeScript.


45
2

Ответы:

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

$(function() {
  // general initialization code goes here, as much as you want
});

У вас может быть несколько таких.


Хорошим шаблоном для этого является диспетчер JS, в котором вы связываете каждую страницу с ее именем контроллера (скажем, атрибутом данных в элементе body). При каждой загрузке страницы вы запускаете небольшой JS-файл, который получает только имя страницы, и запускаете оператор case, который запускает специфичный для страницы JS. Таким образом, вы избегаете подобных проблем и ускоряете работу своего сайта, поскольку вам не нужно запускать JS для незагруженных страниц.

Если вас по-прежнему беспокоят неопределенные элементы, просто проверьте эти элементы перед их использованием.

Например,

class Dispatcher {
  constructor() {
    this.pageName = document.body.dataset.page;
  }

  global() {
    // any global JS here
  }

  route() {
    switch (this.pageName) {
      case 'users:index':
        new Users.IndexFunctionality().init();
        break;
      case 'users:show':
        new Users.ShowFunctionality().init();
        break;
      ...
    }
  }
}


$(document).on('ready page:load', () => {
  new Dispatcher().route();
});