Кэширование URL-адреса/состояния с параметрами

Я делаю мобильное приложение с помощью Cordova и AngularJS. В настоящее время я установил ui-router для маршрутизации, но я открыт для любой другой альтернативы для маршрутизации.

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

Пример ситуации: скажем, что мы видим страницу на панели инструментов, щелкните по обложке книги, которая перенаправляет на путь book/2. Этот путь загружается в первый раз в приложение. Маршрутизатор перенаправляет от HomeController до BooksController (независимо от имени). Теперь BooksController загружает данные для данного $stateParams (book id = 2) и создает представление, заполненное информацией о выбранной книге.

Что я хочу в этой ситуации:

  • Я возвращаюсь на страницу панели мониторинга - он уже загружен (кэширован?)
  • Я снова выбираю книгу # 2
  • Контроллер или маршрутизатор уведомляет, что данные об этой книге уже загружены.
  • Вид не воссоздается, вместо этого он извлекается из кеша

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

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

Любая помощь будет оценена.

EDIT:

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

  • Я не ищу хаки, но ясное решение, если это возможно.
  • Данные в представлениях используют AngularJS, поэтому ДА, есть такие вещи, как ng-bind, ng-repeat и т.д.
  • Кэширование необходимо для данных и элементов DOM. Насколько я знаю, работа с макетом браузера не так дорого, как воссоздание всего дерева DOM. И перерисовать не то, что мы можем опустить.
  • Наличие отдельных контроллеров - это естественная вещь. Поскольку я мог уйти без него, я не могу представить, как это все равно будет работать.

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

Решение 1.

Поместите все представления в один файл (я могу сделать это с помощью конструктора gulp) и используйте ng-show. Это самое простое решение, и я не верю, что кто-то, кто знает AngularJS, не подумает об этом.

A хороший трюк (от @DmitriZaitsev) - создать вспомогательную функцию для отображения/скрытия элемента на основе текущего пути местоположения.

Преимущества:

  • Это легко.
  • Вставка функции предварительной загрузки.

Недостатки:

  • все представления должны быть в одном файле. Не спрашивайте, почему это не удобно.
  • Поскольку все это касается мобильных устройств, иногда я хочу "очистить" память. Единственный способ, который я могу придумать, - удалить этих детей из DOM. Грязный, но нормально.
  • Я не могу легко кэшировать/книгу/2 и /book/ 3 одновременно. Мне пришлось бы динамически создавать DOM файлы поверх некоторых шаблонов для каждого представления, связанного с параметрами.

Решение 2.

Используйте липкие состояния и будущие состояния от ui-router-extras, что является удивительным.

Преимущества:

  • Разделенные виды.
  • Очень простое использование, очень простое, поскольку это просто плагин для ui-router.
  • Может создавать динамические подстанции. Таким образом, можно было бы кэшировать book1, book2, но я не уверен в book/1 и book/2

Недостатки:

  • Опять же, я не уверен, но я не нашел пример с кешированием пары /tuple (view, parameters). Кроме этого это выглядит круто.

Ответ 1

Это именно та проблема, которую мне пришлось решить для моего сайта 33hotels.com. Вы можете проверить его и сыграть с вкладками "Фильтр" и "Список фильтров" (соответствующие различным маршрутам) и увидеть, что представление обновляется мгновенно без задержки!

Как я это сделал? Идея удивительно проста - избавиться от маршрутизатора!

Почему? Поскольку способ работы маршрутизатора - это перекомпилировать представление каждого изменения маршрута. Да, Angular кэширует шаблон, но не скомпилированный вид, заполненный данными. Даже если данные не меняются! В результате, когда я использовал Router в прошлом, коммутатор всегда чувствовал себя вялым и нереактивным. Каждый раз, когда я мог заметить раздражающую задержку, это была небольшая часть секунды, но все же заметно.

Теперь решение, которое я использовал? Не перекомпилируйте свои представления! Храните их внутри DOM в любое время! Затем используйте ng-hide/ng-show, чтобы скрыть/показать их в зависимости от маршрутов:

<div ng-show="routeIs('/dashboard')">
    <-- Your template for Dashboard -->
</div>

<div ng-show="routeIs('/book')">
    <-- Your template for Book -->
</div>

Затем создайте функцию routeIs(string) внутри Controller, чтобы проверить, соответствует ли $location.path() string, или начинается с string, когда я его использую. Таким образом, я все еще получаю свой вид для всех патчей, например /book/2. Вот функция, которую я использую:

$scope.routeBegins = function () {
    return _.some(arguments, function (string) {
           return 0 === $location.path().indexOf(string);               
    });
};            

Так что не нужно быть умным с кешированием - просто держите его в DOM. Он будет кэшировать ваши представления для вас!

И самое лучшее - когда ваши данные будут изменены, Angular мгновенно обновит все Представления внутри вашей DOM, даже скрытые!

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

Есть ли недостатки? Единственным реальным, о котором я могу думать, является загрузка памяти с большим количеством элементов DOM. Однако этот фактический размер байтов моих представлений пренебрежимо мал, сравнивая, например, со всеми JS, CSS и изображениями.

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

Я считаю весьма примечательным, что все используют Маршруты и, похоже, совершенно не знают (или не знают) об этой проблеме.

Ответ 2

1) О статических страницах в приложении (представления), angular берет на себя загрузку.

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

2), если ваша панель сама загружает список книг (или аналогичные данные) через ajax, то вы можете сообщить своему контроллеру только один раз загрузить данные и сохранить их в localstorage, а при последующих запросах на страницу панели мониторинга можно загрузить только данные из localStorage.

3) аналогичный подход можно использовать, когда ваш BooksController загружает данные в представление. Вы можете проверить свой BookController, если запрос для конкретной книги был ранее сделан, и если вы не можете сохранить его в localstorage или в базе данных. и если данные были запрошены ранее, вы можете загрузить те же данные из хранилища без запроса на сервер.

Пример ситуации:

скажем, пользователь делает запрос для book1, затем

  • ваш контроллер i.e BooksController проверяет, были ли ранее запрошены те же данные,
  • Если нет, вы можете загрузить данные через вызов ajax с сервера, а также сохранить его в локальном хранилище.
  • если он был загружен, прежде чем вы загрузите данные, хранящиеся в localstorage или в базе данных.

Ответ 3

Если вы используете ui.router, тогда вы должны взглянуть на дополнительные функции ui.router, в частности на модуль липких состояний. Это позволяет вам кэшировать "дерево" состояния (включая визуализированные представления), поэтому их не нужно компилировать или повторно отображать при изменениях состояния.

http://christopherthielen.github.io/ui-router-extras/

Вот демо:

http://christopherthielen.github.io/ui-router-extras/example/sticky/#/