Метеор: использование сессий и 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
.