Как сделать чтобы скрипт работал только на одной странице

Обновлено: 08.07.2024

В этой статье мы разберёмся, зачем нам это нужно и какие приёмы используются, чтобы этого добиться.

Лишний код

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

Трафик дорожает

В первую очередь ненужный код — это лишний сетевой трафик. Он может быть дорогим, особенно мобильный, особенно в Европе. Сайт или приложение, которые загружают ненужное (особенно изображения), могут оказаться в прямом смысле дорогими.

Время исполнения увеличивается

Удобство работы уменьшается

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

Код и контент

Стратегий борьбы с лишним кодом много: код-сплиттинг и минификация, оптимизация изображений, кэширование, рефакторинг и удаление старого кода.

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

Сплиттингом мы будем называть передачу контента по кускам: когда первый кусок отдаётся автоматически, а остальные — по запросу пользователя.

Такая стратегия используется уже давно, и скорее всего вы уже встречались с её реализацией в виде пагинаторов.

Пагинаторы

Когда сайты были проще, а AJAX и JSON ещё не были распространены, пагинаторы были единственным способом поделить большое количество контента на куски.

Пример пагинатора

Бесконечная прокрутка

Давайте попробуем навестить нашу печально известную соцсеть Switter, знакомую по статье о безопасности веб-приложений, и поможем их разработчикам создать такую бесконечную загрузку. (Может быть хотя бы это убережёт их акции от полного краха.)

Switter сейчас

Сейчас Switter выглядит как лента со свитами и пагинатор внизу.

Switter сейчас

Наша задача — реализовать бесконечную прокрутку. Нам стоит учесть:

Заглушка для сервера

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

Но если вам интересно, как всё устроено — добро пожаловать под капот :–)

Вызывать метод для получения новых постов posts мы будем с помощью await :

Клиент

Когда сервер готов, мы можем приступать к разработке клиентской части. Первым делом спроектируем, как должно работать приложение.

Проектирование

Мы хотим подгружать новый контент, когда пользователь докручивает до конца страницы. Здесь можно выделить несколько задач:

  • Следить за положением прокрутки. Когда мы приближаемся к концу страницы, нужно запрашивать следующую порцию данных
  • Уметь общаться с сервером. Нам нужно отправлять запросы и обрабатывать ответы.
  • Преобразовывать данные в вёрстку на странице и отображать её.
  • Не забыть о правильной обработке события прокрутки, чтобы ничего не тормозило.

Начнём с вёрстки.

Вёрстка и шаблоны

Вёрстка нас устраивает. ( footer можно заменить на menu , но в целом ок.)

Из этой вёрстки мы сделаем шаблон для будущих свитов, которые мы будем загружать с сервера. Шаблон нужен, потому что с сервера мы будем загружать только данные. Как эти данные должны отображаться, сервер не знает. Шаблон будет нужен именно для этого — чтобы браузер мог правильно отобразить данные на странице.

Данные с сервера будут заполнять шаблон, в итоге получится компонент свита

Данные с сервера будут заполнять шаблон, в итоге получится компонент свита.

Отслеживание положения скролла

Дальше нам потребуется написать функцию, которая будет определять, когда пора отправлять новый запрос.

Когда мы докрутим и пересечём порог, отправим запрос за новой порцией контента

Когда мы докрутим и пересечём порог, отправим запрос за новой порцией контента.

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

Улучшение производительности

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

Запросы к серверу

Дальше создадим функцию для запросов к серверу:

И используем её в checkPosition :

Обработка данных от сервера

В функции fetchPosts мы получаем список постов, каждый из которых мы хотим добавить на страницу. Напишем функцию appendPost , которая будет этим заниматься:

Функция appendPost использует внутри себя composePost . Напишем и её тоже:

Цепочка событий

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

В реальном приложении нам бы потребовалось ещё повесить обработчики кликов по кнопкам в этом новом свите. Без обработчиков кнопки не будут ничего делать. Но для краткости эту часть в статье мы опустим.

Добавим обработку данных в fetchPosts :

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

Обработка промежуточных и крайних случаев

Если сейчас запустить приложение, то оно будет работать. Но при прокрутке к концу страницы вместо одной порции контента будет присылать несколько. (И никогда не закончит это делать 😁)

Чтобы решить эти проблемы, нужно завести переменные, которые будут следить за состоянием приложения:

Подправим функцию fetchPosts :

Теперь функция работает правильно.

Что можно улучшить ещё

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

Изменение адресной строки

Хорошим тоном считается, когда мы можем дать ссылку на публичную страницу, и другой человек увидит всё в точности, как мы: сортировку контента, его количество, начало и конец. Для этого используется адресная строка и URL-страницы.

В нашем случае при изменении номера текущей страницы мы можем изменять часть адреса.

Для таких задач можно использовать History API.

Восстановление прокрутки при открытии страницы

Эту задачу часто решают на сервере. Это может быть проще и эффективнее, потому что сервер в таком случае заранее знает, какие данные нужно достать и отдать клиенту. Получается меньше запросов, и приложение для пользователя субъективно быстрее.

Результат

В результате мы получим переработанную страницу Switter, которая будет получать контент в тот момент, когда он нужен пользователю.

На практике

Саша Беспоясов

Используйте throttle для подобных задач, чтобы улучшать производительность.

Я пытался загрузить большой JS-скрипт только один раз. Я не загружаю его при загрузке страницы, так как он не нужен, и замедлит загрузку страницы.

Поэтому я пытался загрузить его с помощью $ .getScript и Modernizr.load jQuery (поскольку я уже использую Modernizr).

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

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

И var flag = true; был установлен в первой строке разговора.js

У кого-нибудь есть идеи, как заставить этот скрипт загружаться один раз при вызове этого теста, чтобы проверить, был ли он загружен, и загружать его только один раз?

** Редактирование / обновление: ** document.getElementsByTagName('head')[0].appendChild(document.createElement('sc‌​ript')).src = 'conversation.js'; может работать, но как мне проверить, загружен ли скрипт уже или нет, и затем вызывать его, только если он еще не включен?

4 ответа

Сначала вам нужно проверить, есть ли скрипт на странице:

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

ES 6 Обновление

ES 6 упрощает это немного:

Жизнь становится проще, если вы убедитесь, что скрипт загружен только один раз в исходном коде. Если php используется для загрузки скриптов, пусть он также обрабатывает зависимости.

Функции являются объектами первого класса, и если объект не существует, он преобразуется в логическое значение false в операторе if.

Однако это приводит к асинхронной загрузке сценария. Использование document.write все еще может загружаться асинхронно. Это означает, что вызов скрипта может быть сделан в другом месте до его загрузки. Вам также может понадобиться запрограммировать создателя обещаний и хранителя обещаний для обработки этих вызовов. Не невозможно, но . onload используется для выполнения обещания, если оно не загружается, мое обещание было нарушено.

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

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

Однако myscript.js может иметь хранителя обещаний. Он может искать глобальный объект, который представляет собой массив обещаний, и, если этот массив существует, запускают обещания.

Если myscript.js загружен с jquery ajax, хранитель обещаний может содержаться с функцией done.

Более простое решение (опять же при условии ES6) будет:

Функция .some() вернет true, если какой-либо из элементов содержит src, являющийся URL-адресом, что позволит вам затем добавить элемент в конец части сценария.


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

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

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

Будет выполняться раньше, чем загрузиться html-строка:

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

Я хочу рассказать о трех способах, как это можно сделать.

Все мои уроки по Javascript здесь.

1 способ. С использованием библиотеки jQuery.

Чаще всего сам им пользуюсь, наиболее простое и удобное решение, но требует подключения библиотеки Jquery.

Вот как преобразиться предыдущий, код, если мы воспользуемся следующим методом.

2 способ. С помощью элемента body и атрибута onload.

3 способ. С помощью объекта window и его свойства onload.

Выбирайте тот способ, который более всего подходит к вашей ситуации, и применяйте его на практике.

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Если JavaScript-кода много – его выносят в отдельный файл, который подключается в HTML:

Здесь /path/to/script.js – это абсолютный путь к файлу, содержащему скрипт (из корня сайта).

Браузер сам скачает скрипт и выполнит.

Можно указать и полный URL, например:

Вы также можете использовать путь относительно текущей страницы. Например, src="https://programka.com.ua/dokument/sistema/lodash.js" обозначает файл из текущей директории.

Чтобы подключить несколько скриптов, используйте несколько тегов:

Как правило, в HTML пишут только самые простые скрипты, а сложные выносят в отдельный файл.

Браузер скачает его только первый раз и в дальнейшем, при правильной настройке сервера, будет брать из своего кеша.

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

В одном теге SCRIPT нельзя одновременно подключить внешний скрипт и указать код.

Вот так не сработает:

Нужно выбрать: либо SCRIPT идёт с src , либо содержит код. Тег выше следует разбить на два: один – с src , другой – с кодом, вот так:

Асинхронные скрипты: defer/async

Браузер загружает и отображает HTML постепенно. Особенно это заметно при медленном интернет-соединении: браузер не ждёт, пока страница загрузится целиком, а показывает ту часть, которую успел загрузить.

Если браузер видит тег , они будут проигнорированы.

Тот же пример с async :

При запуске вы увидите, что вся страница отобразилась тут же, а alert из внешнего скрипта появится позже, когда загрузится скрипт.

Большинство современных систем рекламы и счётчиков знают про эти атрибуты и используют их.

Читайте также: