Одна из моих любимых вещей в Vue.js — он работает на простейших страницах с простейшими компонентами. Вам не нужны никакие сложные инструменты сборки или деревья зависимостей.
Но Vue не ограничивается только простыми компонентами. Vue-resource делает AJAX простым, с vue-router можно настроить маршрутизацию одностраничного приложения почти без усилий. И я обещаю, когда-нибудь я выучу и Vuex.
Я хочу показать вам, насколько просто использовать vue-router для создания одностраничного приложения с помощью Vue. И уж поверьте мне — это просто. Если вы уже создавали свой компонент с помощью Vue, то 90% работы позади.
Настройка
Как это часто бывает, в качестве инструмента для сборки я выбрал Laravel Elixir.
Вы можете использовать любую систему сборки, которая предоставляет вам доступ к вашим NPM-пакетам. Или вы можете включить пакет в сборку вручную (с помощью CDN ) или с помощью Bower. В итоге вам нужен vue-router, установленный любым способом. Если вы не собираетесь использовать Elixir, то просто пропустите следующий раздел.
Установка Vue и vue-router с помощью Laravel Elixir (не обязательно)
Если вы собираетесь начать новый проект используя Laravel Elixir, прочтите документацию с инструкциями по базовой установке. Затем добавьте vue и vue-router:
shnpm install vue vue-router --save
Далее вам надо добавить задачу Browserify для вашего JavaScript файла:
js// gulpfile.js elixir(function (mix) { mix.browserify('app.js'); });
Теперь ожидается, что у вас есть файл resources/assets/js/app.js, который будет передаваться через Browserify и Babel и выводиться в public/js/app.js. Создайте «ресурсную» версию этого файла и выполните shgulp watch
, чтобы запустить его.
Включение зависимостей
Вам надо включить Vue и vue-router в свой основной JavaScript файл с помощью любой доступной вам системы импорта:
jsvar Vue = require('vue'); var VueRouter = require('vue-router'); Vue.use(VueRouter);
Мы включили Vue и vue-router, и затем связывали их друг с другом. Теперь давайте напишем наше приложение.
Создание своего приложения
Как в любом Vue-приложении, нам надо создать базовое приложение. Но в отличие от других Vue-приложений, ядро шаблонной работы, которую мы будем делать, это отображение нескольких компонентов по нескольким маршрутам. Во Vue нет такого нового понятия как «страница», каждая страница — это просто компонент, который может содержать другие компоненты.
Давайте создадим наше приложение и наш маршрутизатор:
jsvar App = Vue.extend({}); var router = new VueRouter(); router.start(App, '#app');
Вот и всё! Оно не будет ничего делать, потому что мы не отобразили ни одного маршрута, но мы определили приложение, определили маршрутизатор, собрали их воедино, и затем инициализировали маршрутизатор.
Отображение компонентов по маршрутам
У нас есть приложение и маршрутизатор, давайте определим несколько маршрутов:
jsvar App = Vue.extend({}); var router = new VueRouter(); var Home = Vue.extend({ template: 'Добро пожаловать на <b>главную страницу</b>!' }); var People = Vue.extend({ template: 'Посмотрите на всех, кто тут работает!' }); router.map({ '/': { component: Home }, '/people': { component: People } }); router.start(App, '#app');
Мы определили два возможных маршрута в нашем приложении и указали компонент для каждого из них.
Сборка HTML-страницы
Давайте создадим HTML-страницу для размещения нашего маршрутизатора. Этой странице не обязательно быть полностью пустой, как вы могли бы подумать. При использовании vue-router ваше приложение может содержать какой-либо код, и он не будет отключен из-за использования компонентов, например, это может быть панель навигации.
xml... <div id="app"> <a v-link="{ path: '/' }"><h1>Our company</h1></a> <ul class="navigation"> <li><a v-link="{ path: '/people' }">People</a></li> </ul> <router-view></router-view> </div> ...
Предположим, у этой страницы есть HTML-заголовок и блочные теги, а также она импортирует наши скрипты и зависимости где-нибудь в заголовке или подвале.
Здесь мы видим несколько важных вещей. Во-первых, когда мы запустили наш маршрутизатор в скрипте, мы связали его с '#app', поэтому нам надо создать элемент страницы с ID = «app», с которым мы свяжем наше Vue-приложение.
Во-вторых, здесь использован Vue-синтаксис для ссылок — используется свойство v-link и передаётся в JSON-объект. Мы будем делать так: { path: '/url-here' }.
Если открываемая в данный момент ссылка «активна» (открыта у пользователя), маршрутизатор применит для неё класс v-link-active, и вы сможете настроить для неё уникальный стиль. Также вы можете изменить этот класс или применять его для отдельных связанных элементов, таких как родительские div или li — вы можете узнать больше из документации.
И наконец, у нас есть компонент <router-view>, сюда будет приходить вывод каждого компонента.
Если вы зайдёте на эту страницу, и всё корректно загрузится, значит вы сделали своё первое одностраничное приложение с помощью vue-router!
Вы могли заметить, что сейчас в нём используется шебанг-стиль навигации, то есть все ваши маршруты начинаются с #!. Это можно отключить, мы поговорим об этом позже, но приготовьтесь, потребуется немного танцев с бубном.
Более продвинутое определение маршрута
Выше мы определили несколько довольно простых маршрутов. Давайте копнём немного глубже в направлении типов маршрутов, которые можно определить с помощью vue-router.
Параметры маршрута
Возможно вам понадобится определить более сложные маршруты, чем просто статические URL.
Мы будем вызывать URL, которые могут соответствовать нескольким «динамическим» URL. Посмотрим, как определить такой маршрут.
jsrouter.map({ '/people/:personId': { component: { template: 'Person ID is {{$route.params.personId}}' } } });
Из этого примера мы можем узнать несколько вещей.
Во-первых, мы видим, что vue-router отображает динамические параметры используя такой синтаксис: :paramName.
Во-вторых, мы видим, что vue-router позволяет при желании определять объекты компонентов в строку.
И в-третьих, мы видим, что у нас есть доступ к объекту $route со свойством params, который является объектом всех подходящих параметров динамических URL.
Маски сегментов маршрута
Когда надо определить сегмент динамического маршрута, который может подходить для нескольких сегментов, используйте в начале имени сегмента * вместо : :
jsrouter.map({ '/people/*greedy' => {}, '/people/*greedy/baz' => {}, });
Первое определение маршрута будет подходить для /people/a, /people/a/b, /people/a/b/c/d/e/f.
Второе определение маршрута будет подходить для /people/a/baz, /people/a/b/c/d/e/f/g/baz и т.д.
Оба будут возвращать сегмент greedy по маршруту $route.params.greedy, что эквивалентно полной строке для этого сегмента. /people/a/b/baz будет возвращать { greedy: 'a/b' }.
Именованные маршруты
Если вы когда-либо использовали маршруты Laravel, то вы уже знакомы с идеей — давать любому маршруту «имя», на которое можно ссылаться позже. С vue-router это тоже возможно:
jsrouter.map({ '/people/:personId': { name: 'people.show', component: People } });
Далее вы можете ссылаться на этот маршрут с помощью v-link:
xml<a v-link="{ name: 'people.show', params: { personId: 5 }}">Person 5</a>
Переход по маршруту в JavaScript
Мы рассмотрели, как v-link может заменять обычные ссылки, а что если вам надо инициировать событие перехода в вашем JavaScript? Тут вам поможет router.go():
jsrouter.go({ name: 'people.show', params: { personId: 5 }});
Также вы можете использовать router.replace(), который работает так же, но при этом не создаёт новой записи в истории браузера.
Настройки маршрутизатора
Когда вы создаёте экземпляр объекта маршрутизатора в начале вашего JavaScript-файла, вы можете передать в него несколько параметров для настройки.
- hashbang — если задать значение false, система будет использовать настоящие URL (/people) вместо шебанга (/#!/people). Если вы сделаете так, то вам надо будет включить history и соответственно настроить свой сервер.
- history — использует момент отправки в браузере для обновления истории посещений в нём при переходах на сайте. Требует правильной настройки вашего сервера.
- root — если ваше приложение находится не в корне на сервере, то задайте это свойство для указания правильной подпапки, в которой находится приложение. Например, если ваше приложение находится в /app, то задайте значение /app, тогда vue-router будет генерировать соответствующие URL — /app/people вместо /people.
Если вы используете это приложение внутри Laravel-приложения, то вместо настройки nginx или Apache для обработки без-шебангового состояния отправки вы можете настроить своё Laravel-приложение для его обработки. Просто установите маршрут для захвата всех валидных URL и передачи их в представление, выводящее ваш Vue-код:
js Route::get('/{vue_capture?}', function () { return view('home'); })->where('vue_capture', '[\/\w\.-]*');
Получение информации маршрута в ваших компонентах
У каждого компонента в вашем приложении будет доступ к this.$route, который является «контекстным объектом маршрута» и предоставляет свойства, которые могут быть полезны для получения информации о вашем маршруте. У ваших шаблонов тоже будет доступ к этому объекту через $route.
- $route.path эквивалентен абсолютному пути, например, /people
- $route.params содержит пары ключ/значение ваших динамических разделов, например, { personId: 5 }
- $route.query содержит пары ключ/значение вашей строки запроса, например, /people?sortBy=names будет возвращать { sortBy : lastName }
- $route.router возвращает экземпляр vue-router
- $route.matched возвращает объекты конфигурации маршрута для каждого подходящего сегмента в текущем маршруте
- $route.name возвращает имя текущего маршрута, если таковое имеется
Вы также можете передать в свои компоненты произвольные данные, передав их в определение маршрута. Например, я хочу, чтобы некоторые секции моего приложения были доступны только администратору, тогда я передаю это в виде флага в определение маршрута, а внутри компонента проверю его наличие как $route.adminOnly.
jsrouter.map({ '/secret-admin-panels': { component: SecretDashboard, adminOnly: true } });
Настройка хуков
Я мог бы проверять свойство $route.adminOnly в своих компонентах, но ещё лучше, если это будет обработано до того, как пользователь получит доступ к компоненту, при помощи посредника. При использовании vue-router это будут хуки маршрута, такие как beforeEach:
js// Пример проверки доступа пользователя var MyUser = { admin: false }; router.beforeEach(function (transition) { if (transition.to.adminOnly && ! MyUser.admin) { transition.redirect('/login'); } else { transition.next(); } });
Как видите, мы перехватываем запрос перед отрисовкой компонента. Мы можем разрешить дальнейший переход с помощью transition.next(), а также мы можем перехватить пользователя и перенаправить или отменить переход — transition.abort().
Существует также хук afterEach().
Разное
Ещё несколько последних замечаний.
Первое, <router-view> может быть передан точно так же, как и любой другой страничный компонент.
Второе, для Vue есть полное описание переходов, которое можно использовать для определения визуального и функционального поведения при переходах между страницами.
Третье, эта статья охватывает далеко не всё, загляните в документацию.
Заключение
Вот теперь всё. Вы увидели насколько просто настроить своё первое одностраничное приложение при помощи Vue и vue-router, и насколько плавный переход от единственного компонента к одностраничному приложению.
Если хотите посмотреть на (какой-нибудь) работающий пример использования vue-router, то можете взглянуть на обучающее приложение Suggestive, над которым я сейчас работаю.
Комментарии (2)
а можно без npm? я хочу в script подключить vue-router и по клику на кнопку отображать другую страницу. может мне и роутер в данном случае не нужен? я вообще то слабо представляю зачем он?
Привет. Если правильно тебя понимаю, ты можешь сделать каждую страницу своего сайта отдельным одно-страничным приложением, в этом случае ты вполне можешь обойтись и без роутера.