Метеор: использование сессий и ReactiveVar

Когда вы должны использовать Session и ReactiveVar? Я использую переменную Session как среду связи между компонентами. Например, посмотрите на Stackoverflow.

введите описание изображения здесь

Я обозначил три гипотетических компонента. Посмотрим на компонент filters. Если вы нажмете Tags, тогда компоненты Main будут отображать свои вопросы на основе ваших любимых тегов. Для этого я устанавливаю Session.set("Main/showTags", true) при нажатии кнопки Tags. В основном компоненте у меня будет вспомогательная функция, как показано ниже:

Template.Main.helpers({
  posts: function() {
    var isTags = Session.get("Main/showTags");
    var isQuestions = Session.get("Main/showQuestions");
    ...
    if (isTags) {
      return Posts.find().sort({tags: 1}) // or something along the lines
    } else if (isQuestions) ...
  }
});

В большинстве случаев это сработало хорошо, но я видел из многих мест, что я должен воздержаться от использования Session и использовать ReactiveVar. Но если я использую ReactiveVar всюду, то мне нужна ссылка на все экземпляры шаблона. Я ожидаю, что он будет хорошо работать между прямыми родительскими и дочерними шаблонами (например, внутри основного компонента, может быть VoteAnswerViewsButtonTemplate), но как вы это сделаете с помощью ReactiveVar, когда вы хотите, чтобы независимые компоненты разговаривали друг с другом?

Вот мой последний вопрос. Как я могу соответствующим образом использовать Session и ReactiveVar, чтобы сохранить область компонентов и заставить их общаться друг с другом? Кроме того, если я использую Session способ, который я делаю сейчас, могу ли я загрязнять глобальное пространство имен без необходимости?

Связанные документы:

Ответы

Ответ 1

Насколько я знаю, нет встроенных функций, связанных с переменными Session, которые отличает их от обычной глобальной переменной реактивного словаря (например, @Kyll заявлено), что вы бы заявили, например, в своем client.js файле. Единственное отличие состоит в том, что Session "ограничение" является необходимым доступным приложением в целом.

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

1 - Глобальная область. Например. текущий язык пользовательского интерфейса, пользовательский интерфейс. Для этого я использую Session. Простые и глобальные данные, а не то, что можно смутить ни с чем другим.

2 - Кластер шаблонов. Скажем, например, что я создаю страницу для создания и настройки PDF файлов в моем приложении. Я не буду повторно использовать какие-либо компоненты в другом месте. Мой кластер - это папка с тремя файлами, позвоните им pdfgenerator.html, pdfgenerator.js и pdfgenerator_controller.js.

Я использую pdfgenerator_controller.js для расширения маршрута со всеми особенностями.

В файле pdfgenerator.js у меня есть несколько шаблонов, которые я использую в кластере. В начале файла я создаю реактивный словарь pageSession (похожий на реактивные переменные), и я использую его во всем моем кластере. Это позволяет мне передавать данные среди всех моих компонентов.

3 - Локальная область. Является ли это одним шаблоном или компонентом многократного использования, он предназначен для работы в одиночку. Я тоже не буду использовать Session vars для них. Я не хочу переполнять пространство имен Session. То, что я делаю, - это передать моему шаблону все данные, которые мне нужны для его работы во время его создания.

Это может быть из Spacebars:

{{> mySingleTemplate data=myData}}

или используя Javascript:

Blaze.renderWithData(Template.mySingleTemplate , myData, self.firstNode);

В случае с локальной областью я также использую reactive dictionary или reactive vars только для обработки реактивности, происходящей внутри одного шаблона. В этом случае я стараюсь избегать ситуаций, когда мне нужно оперативно возвращать данные родительскому шаблону. Если мне нужно (т.е. Я, вероятно, не сделаю из него пакет), я использую локальную коллекцию minimongo, объявленную как глобальную, в области родительского шаблона. Таким образом, я могу передать информацию из повторно используемого компонента в родительский.

Пример: шаблон загрузки. Я использую minimongo для хранения имени, размера, типа, статуса и URL каждого загруженного файла. Коллекция minimongo разделяется между шаблоном родительской формы и шаблоном дочернего загрузчика.


Нижняя строка: Я использую только переменные Session для базовой и глобальной информации. Если структура данных, необходимая для совместного использования в глобальном масштабе, слишком сложная/большая, я полагаюсь на коллекцию.

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

Ответ 2

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

  • Вы не можете прятать имена переменных var (например, wtf имеет значение isColumnHidden снова)? Или, сеансовые vars образуют естественные кластеры (3 сеанса vars для всплывающих подсказок, 5 для тегов и т.д.).
  • Вам нужна информация о сеансе в URL-адресе, чтобы вы могли отправить кому-то ссылку, и они видят, что вы видите.

Итак, как вы решаете каждую проблему?

  • В первом примере создайте пакет. Например, в одном из моих больших проектов я создаю пакет rightSideMenu и leftSideMenu. Каждый из них имеет свой собственный ReactiveDict, который я экспортирую в глобальную область (например, rightMenu.RD.get('col1Hidden')). Это сохраняет подход модульным. Я могу полностью переписать свой код меню, но пока я все еще выставляю ReactiveDict, API остается прежним. Тем не менее, я все еще использую Session var для отображения/скрытия левого и правого меню. Зачем? потому что сеанс идеально подходит для меню. Я не хочу, чтобы скрытое меню сохранялось через сеансы браузера (когда-либо закрывали то, что вы не знали, как его открывать?), Но я хочу, чтобы он сохранялся через маршруты. Другими словами, я хочу, чтобы это продолжалось для этого сеанса просмотра.

  • Если вы хотите, чтобы url сохранял информацию о сеансе, вам нужно использовать параметры или параметры запроса. Например, если у вас есть карта с 100 маркерами, и пользователь хочет отправить эту страницу своему собеседнику с выбранным определенным маркером, имеет смысл, что URL-адрес будет похож на url.com/marker20. Но зачем останавливаться? Вы также можете включить lat и lng центра карты: url.com/marker/40.23432/122.2342. Может быть, это слишком много, может быть, нет. Вам решать. В вашем примере это делает LOT более ощутимым, чем сохранение isTag в сеансе var, поскольку позволяет пользователям закладок, использовать кнопку "Назад", делиться им и изменять его, не используя свою мышь (да, ваша пользовательская база такая же ленивая, как и Я).

Дополнительная заметка о вашей текущей настройке заключается в том, что вы используете флаги для чего-то, что является взаимоисключающим, что приводит к условному аду. Если у вас есть 2 vars, которые не могут быть истинными, остановите и переосмыслите дизайн. Итак, если бы я использовал сессионные вары, я бы сделал что-то вроде:

 currentTemplate = Session.get('filter') 
 {{Template.dynamic template=currentTemplate}}

В конце концов, вам нужно подумать о многом больше, чем просто ReactiveVariables. Как насчет зависимостей? Не каждому модулю требуется доступ к зависимостям каждого другого модуля. То же самое касается коллекций, методов и даже CSS. Я говорю, пусть он вырастет органично, и когда он ударит вас "эй, это компонент", затем превратите его в пакет, экспортируйте переменную и сохраните ее по модулю. До этого момента сеансовые сеансы в порядке.

Ответ 3

Ваша проблема не загрязняет глобальную область. Тогда почему бы не сделать свой собственный?

myComponentScope = {}; //Declare a global scope for this component

Тогда просто поместите столько вещей, сколько хотите внутри. Например,

myComponentScope.foo = new Reactive-Var('foo');

И если вы хотите что-то похожее на Session, вы можете добавить Reactive-Dict:

meteor add reactive-dict

И используйте его так:

myComponentScope = new Reactive-Dict(/* Optional name */);

Необязательное имя делает словарь постоянным через нажатие горячего кода.
API для этого словаря совпадает с Session.


Таким образом, если у вас есть что-то строго локальное (один шаблон), перейдите к Reactive-Var.
Когда это что-то несколько шаблонов одного и того же рода, идите в свою область.
Если это так важно, все ваше приложение вам понадобится, используйте Session.