Подгрузка внешних JS скриптов “по событию”

150
01 июня 2019, 20:20

Хочу реализовать следующий подход - подключать некоторые внешние скрипты только если на странице присутствуют DOM элементы использующие их (с определенным классом). Например загружается страница и если присутствует хоть один элемент document.querySelector('.ymaps-geolink') подгружается API Geolink Yandex. Таким образом я хочу предусмотреть в скрипте десятки разных хуков которые могут и не использоваться в текущем проекте, но если уж понадобились для подключения достаточно прописать только нужный класс у элемента.

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

<script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&load=Geolink" 
 type="text/javascript"></script> 
 
<span class="ymaps-geolink"> 
   Москва, ул. Крылатские холмы, 26 
</span>

Примерно что я хочу (извиняюсь за php синтаксис)

$plugins=[
    ".ymaps-geolink"    => "https://api-maps.yandex.ru/2.1/?lang=ru_RU&load=Geolink",
    ".tooltip"          => "https://cdnjs.cloudflare.com/ajax/libs/jquery/tooltip.js",
    ...
    ...
];

function onload(){
    foreach($plugins as $k=>$v){
        if( document.querySelector($k) ){
            include_once($v);
        }
    }
}
Answer 1

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

Я бы сделал следующим образом:

  1. Проитерировать коллекцию оставив только те элементы, классы которых присутствуют на странице. Таким образом мы получим список всех скриптов, которые необходимо использовать для страницы.
  2. Перебрать полученную коллекцию и для каждого элемента динамически создать html тэг, подключающий файл.

'use strict'; 
 
/* коллекция: объект, где имя свойства соответствует искоемому классу, а значение - обрабатывающиму скрипту */ 
let scriptCollection = { 
  redColor: 'red-color.js', 
  removeElement: 'remove-element.js', 
  alert: 'alert.js' 
} 
 
const dynamicScript = (collection) => { 
 
  let scripts = []; /* коллекция необходимых скриптов */ 
 
  /* собираю коллекцию необходимых скриптов */ 
  for (let key in collection){ 
    if (document.querySelectorAll(`.${key}`).length){ 
      scripts.push(collection[key]); 
    }; 
  } 
 
  /* добавляю скрипты на страницу */ 
  scripts.forEach((item) => { 
    let scriptTag = document.createElement('script'); 
    scriptTag.setAttribute('src', item); 
    scriptTag.setAttribute('async', ''); 
    document.body.appendChild(scriptTag); 
  }); 
} 
 
/* вызов функции */ 
dynamicScript(scriptCollection);
<html> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <title>Pointer</title> 
    <style> 
        body{ 
            display: flex; 
            flex-direction: column; 
            justify-content: center; 
            align-items: center; 
        } 
    </style> 
</head> 
<body> 
    <div class="redColor">123</div> 
    <div class="removeElement">123</div> 
    <div class="alert">123</div> 
</body> 
<script defer src="index.js"></script> 
</html>

READ ALSO
Найти минимальную дату из трех в формате ДД.ММ.ГГГГ?

Найти минимальную дату из трех в формате ДД.ММ.ГГГГ?

Найти минимальную дату из трех в формате ДДММ

168
Форма HTML + jquery для отправки rest запроса

Форма HTML + jquery для отправки rest запроса

Есть контроллер на java обрабатывающий post запрос

133
помогите разобраться с функцией split() в jQuery

помогите разобраться с функцией split() в jQuery

выдает typeError: undefined is not an object (evaluating 'valuessplit')

115