Статьи

Создание многостраничного сайта с Meteor

Как и в любом веб-приложении, создание многостраничных сайтов требует специального набора инструментов. В этой статье мы рассмотрим разработку библиотеки, которая может не только различать различные URI, но и использовать основные функции Meteor .


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

Итак, мы можем начать с записи некоторых функций, которые мы хотели бы иметь:

  • Возможность загрузки разных страниц в соответствии с URI
  • Чтение параметров из URI (заполнителей)
  • Сохранение страниц динамическими в соответствии со стандартом Meteor

Это выглядит довольно хорошо. Теперь, посмотрев на эти функции, вы можете подумать, что они очень похожи на библиотеку типа «маршрутизатор», и я согласен. Итак, давайте посмотрим, как наша библиотека «маршрутизатор» будет работать в действии:

В дизайне у вас есть такие понятия, как «форма следует за функцией», в которой используется идея сначала все спланировать, а потом спроектировать.

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

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

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

  • Мы начнем с получения URI текущей страницы, так как нам нужно сопоставить маршруты с чем-либо. Это можно сделать довольно легко, используя переменную window.location.pathname , предоставленную браузером.
  • Далее нам нужна возможность добавлять маршруты. Это также, довольно просто, теперь, когда мы сделали некоторый пример кода; у нас будет функция с именем addRoute которая будет принимать шаблон маршрута и имя шаблона. Эта функция должна будет хранить все эти объекты маршрута внутри какого-либо массива.
  • С сохраненным текущим URI и массивом маршрутов нам понадобится какой-то метод, чтобы увидеть, совпадают ли они.
  • И последнее, но не менее важное: нам нужно выбрать подходящий маршрут и отобразить прикрепленный к нему шаблон.

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


Для начала давайте создадим новый проект Meteor, я собираюсь назвать мой routerdemo . Теперь внутри мы создадим папку с именем « lib » внутри другой папки с именем « client »:

1
2
3
meteor create routerdemo
cd routerdemo
mkdir -p client/lib

Затем создайте файл с именем router.js во вновь созданной папке lib . Причина, по которой мы помещаем его в « client », заключается в том, что сервер не имеет доступа к переменной window.location.pathname и, как таковой, не будет работать с нашим маршрутизатором. Помещение вещей в папку с именем client гарантирует, что они будут запускаться только на стороне клиента.

Теперь внутри файла router.js который вы только что создали, давайте router.js некоторые леса:

Я думаю, что это довольно хороший скаффолд, я даже заполнил код для массива маршрутов и добавил несколько комментариев (прогресс!). Теперь для дальнейшего развития нашей библиотеки нам нужно обсудить, как мы собираемся совместить эти маршруты вместе.


Это не так просто, как currentRoute === route , так как мы имеем дело с динамическими заполнителями. Мы хотим, чтобы маршрут для ‘ /user/:id ‘ совпадал с URI ‘ /user/42 ‘ и так далее.

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

Этого легко достичь, разделив URI там, где есть косая черта (‘/’), используя метод .split . Таким образом, наша первая проверка будет гарантировать, что два маршрута имеют одинаковое количество сегментов.

Если маршрут « /user/:id » и мы получаем URI « /profile/42/foo/bar », нам даже не нужно выполнять дополнительную проверку, у одного есть два сегмента, а у другого четыре, так что это кажется хорошей первичной проверкой. Следующее, что мы можем сделать, это отфильтровать списки и убедиться, что каждый фрагмент, который не является заполнителем, совпадает. Если эти две проверки верны, мы знаем, что маршрут соответствует.

Итак, начнем с установки переменной uri :

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

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

Вот завершенная функция:

Мы начнем с разбиения маршрута на сегменты, как мы это делали для URI, но на этот раз нам также нужно сохранить индексы заполнителей для будущей ссылки, используя метод reduce Underscore.

Для неосведомленных, функция Reduce похожа на each метод, она также циклически перебирает все элементы списка, с той разницей, что она передает то, что каждая итерация возвращает следующему элементу, в конечном итоге возвращая результаты в данную переменную. Мы начинаем с пустого массива (3-й параметр) и добавляем каждый индекс по мере его нахождения и передаем этот массив до тех пор, пока, наконец, он не вернется обратно в переменную placeholders .

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

Наконец, мы помещаем новые данные в наш массив маршрутов, который мы создали ранее.

Следующим шагом является фильтрация по списку и поиск маршрута, который соответствует текущему URI.

Вот полная функция:

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

Затем мы выполняем начальную проверку, чтобы убедиться, что два маршрута имеют одинаковое количество сегментов, в противном случае мы просто перейдем к следующему маршруту. Если они имеют одинаковое количество компонентов, мы должны проверить, совпадают ли сегменты, это можно сделать с помощью функции Underscore « _.every ». Эта функция снова похожа на метод _.each , за исключением того, что она возвращает логическое значение. Это работает так, как если бы они все возвращали значение true, функция запускала бы функцию для каждого элемента в массиве, в противном случае она возвращает значение false, поэтому она идеально подходит для таких вещей, когда нам нужно проверить каждый сегмент. ,

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

Чтобы проверить, является ли это заполнителем или нет, мы передаем индекс текущих сегментов (сохраненный в « i ») в функцию _.contains Underscore, которая проверит его значение.

Теперь вам может быть интересно, что делает первая строка в этом операторе « if », ну, он хранит сегмент в массиве данных под заданным именем заполнителя. Например, скажем, у вас был маршрут ‘ /user/:name ‘, а текущий URI — ‘ /user/bob ‘, тогда эта строка добавит свойство к объекту данных с именем ‘ name ‘ и передаст ему значение bob

Остальное довольно очевидно, мы передаем true или false, в зависимости от обстоятельств, и результат сохраняется в « match ». Если match равно true, мы возвращаем данные вместе с именем шаблона, а если совпадений не было, мы возвращаем false. И это все для нашего метода getMatchingRoute .

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


Метеор использует руль для шаблонов и сохраняет все шаблоны в переменной с соответствующим названием « Template ». Теперь, если вы знакомы с рулями, вы знаете, что эти шаблоны являются просто функциями, и, вызывая их (необязательно передавая некоторые данные), мы получаем HTML-код шаблона.

Теперь вызов этих функций для получения HTML шаблона будет работать нормально, но он не очень похож на Meteor, поскольку в итоге мы получим обычный статический веб-сайт. К счастью, добавить динамическое поведение проще, чем вы думаете, все, что нам нужно сделать, это обернуть вызов функции в вызов « Meteor.render ». Помещение в эту функцию заставит ее реагировать на изменения в данных и поддерживать их в рабочем состоянии.

Из-за этого запустить маршрутизатор очень просто, давайте создадим метод run:

Мы начинаем с получения совпавшего маршрута, используя функцию getMatchingRoute которую мы только что написали, затем мы getMatchingRoute , есть ли совпадение, и, наконец, используем оператор else для обработки отображения 404.

Внутри оператора if мы вызываем Meteor.render а внутри мы проверяем и вызываем возвращенный шаблон, передавая вместе с ним данные от заполнителей. Эта функция вернет HTML-фрагмент, который мы затем можем просто добавить в тело документа.

Итак, имея около 60 строк кода, мы завершили наш маршрутизатор.

Следующий шаг — проверить это. Я собираюсь использовать тот же код, который мы написали ранее, когда планировали этот проект, так как это будет хорошим показателем того, достигли ли мы того, чего хотели. Давайте добавим файл с именем main.js в папку client и добавим следующее:

В приведенном выше коде мы должны сначала убедиться, что наши шаблоны и тело будут доступны, прежде чем мы попытаемся работать с нашим маршрутизатором. Мы делаем это, оборачивая весь наш код внутри Meteor.startup метода Meteor.startup . Это гарантирует, что все готово, и в методе startup мы можем добавить наши маршруты и запустить маршрутизатор.

Теперь давайте создадим пару шаблонов, это можно сделать где угодно, вы можете создать подпапку в папке client именем templates и создать отдельный файл HTML для каждого, но так как это будут короткие шаблоны и только для примера, я собираюсь поместить их вместе в файл с именем ‘ templates.html ‘ внутри папки ‘ client ‘:

01
02
03
04
05
06
07
08
09
10
11
12
13
<template name=»homeTemplate»>
    <h1>This is the Home Page</h1>
</template>
 
<template name=»profileTemplate»>
    <h1>Profile Page</h1>
    <p>Welcome back {{username}}</p>
</template>
 
<template name=»contactTemplate»>
    <h1>Contact Page</h1>
    <p>Contact me on twitter at {{twitterName}}</p>
</template>

Первый шаблон довольно простой, он просто содержит небольшой HTML-код для заголовка домашней страницы. Второй шаблон очень похож на первый шаблон, но на этот раз мы используем параметр маршрута username . Теперь последний шаблон также использует заполнитель, но его маршрут не имеет сегмента twitterName . Это потому, что стандартные заполнители Meteor все еще будут работать и работать реактивно.

Вернемся в папку client , теперь давайте создадим файл с именем ‘ templates.js ‘, чтобы объявить контактный заполнитель.

Вы могли бы просто вернуть строку, но я хотел продемонстрировать, что все по-прежнему реагирует. Последний шаг — удалить html и js файлы по умолчанию из корневого каталога (в моем случае они называются routerdemo.html и routerdemo.js). После этого запустите сервер Meteor и перейдите к заданным маршрутам.

Попробуйте перейти в « /home » или « user/gmanricks » или « /contact », и все они должны работать для вас, как и ожидалось. Другое дело, что поскольку мы сохранили имя Twitter в Session, мы можем просто открыть консоль браузера на странице контактов и ввести:

И вы увидите, что страница будет обновляться в режиме реального времени!


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

В конце, я надеюсь, я понял, что здесь не происходит никакой «магии». Это действительно все о реализации того, что вам нужно, а не о том, что вы можете.

Спасибо за чтение, надеюсь, вам понравилось. Как всегда, если у вас есть какие-либо вопросы, вы можете оставить их ниже или задать их в IRT NetTuts или в моем Twitter.

Метеор Стартовая Книга

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